I am building a textbased game, and I have problem of how to build/structur my SQL table for items.
Item can be anything from weapon, a fruit, armor, etc. But I'm not sure how to properly design this.
For example
Iron Sword Str +4 Health +3
(Or something like that)
But if its a fruit item
Fruit of Health (lol)
+5 health when eated
Any tips or ideas? The question is How do I structure this SQL table?
Store different types of object in different tables.
Give each table the proper columns for the respective kind of object it stores.
CREATE TABLE Weapons (WeaponId INT PRIMARY KEY, Name VARCHAR(20), Strength INT);
CREATE TABLE Foods (FoodId INT PRIMARY KEY, Name VARCHAR(20), HealthBonus INT);
If you want all types of objects to have some common attributes, like weight or purchase price, then you could create a general Items table that has those common attributes.
CREATE TABLE Items (ItemId INT AUTO_INCREMENT PRIMARY KEY,
Weight NUMERIC(9,2), Cost NUMERIC(9,2));
You'd make the WeaponId and FoodId primary keys from the other tables would each match one of the ItemId values in Items. When you want to create a new weapon, you'd first add a row to Items which would generate a new ItemId value, then use that value explicitly as you insert into Weapons.
See the Class Table Inheritance pattern.
Re your question below.
If you are querying for a specific weapon, you can join:
SELECT * FROM Items i JOIN Weapons w ON w.WeaponId = i.ItemId
WHERE w.Name = 'Iron Sword';
If you are query for all items in the character's backpack, you'd have to do multiple joins:
SELECT i.*, COALESCE(w.Name, f.Name, t.Name) AS Name,
CONCAT_WS('/',
IF (w.WeaponId, 'Weapon', NULL),
IF(f.FoodId, 'Food', NULL),
IF(t.TreasureId, 'Treasure', NULL)
) AS ItemType
FROM Items i
LEFT OUTER JOIN Weapons w ON w.WeaponId = i.ItemId
LEFT OUTER JOIN Foods f ON f.FoodId = i.ItemId
LEFT OUTER JOIN Treasure t ON t.TreasureId = i.ItemId
etc.;
If a given Item matches a Weapon but not a Food, then the columns in f.* will be null. Hopefully a given ItemId matches an Id used in only one of the specific subtype tables. On the other hand, it allows a given item to be both a weapon and a food (for instance, vegan cupcakes, which can be effective projectiles ;-).
Sounds like you need a table of attributes (strength, health, etc.). Then a table of the items (name, description, etc) and an association linking the two together (obviously linking by related id's rather than text for normalization, but this is just to demonstrate).
Item Attr Value
Iron Sword Str +4
Iron Sword Hlth +3
Fruit Hlth +5
Right answears given above.. They are different approaches... The second one requires good knwledge of OOP.
I want to mention an other thing, I suggest you read some tutorial on Entity Relational diagram-design. I gues for a game you will probably need to study a few basic things only so it will take you only some hours I guess.
There are many things to consier while designing... for example:
Entity = A thing that can logically stand on its own with its own attributes: Customer, Supplier, Student, Departement are some strong entities etc. Works for, belongs to etc are not entities but relations that associatin entities together.
An entity becomes a table. Strong entities (that have no dependencies) become tables with a simple primary key and usually without accepting any foreign keys. Phone number is not a strong-indepndent entity every time a customer is deleted the phone has no menaing, every time a phone is deleted hte customer has still meaning. Phone is an attribute but because of multiple values it becomes finally a table.
All these are not to tutor er design just to mention that db design in not something to take lightly, it can save you or give you big pain... depends on you.
Related
I have been looking around for answers for countless hrs and could not find much.I am making a food project and I was wondering if there is a way to prevent 2 items with the same name from colliding each other with their 2nd table.To make things clear I have 1 table which is
CREATE TABLE cuisine (id int,dish_name varchar(32));
//2nd table CREATE TABLE ingrediant (id int,dish_name varchar(32),ingrediant);
I was wondering if lets say 2 people posted dish_name = pizza with different ingrediants,when i left join how would the tables know which one to join because the only thing that are matching is the dish_name.
I know i could add the ingrediants to the first table but lets say i am adding up to 50 ingrediants and other items it is too much stuff.
An example i can use is Ebay.
If 2 people post items with the exact same name,when the item is clicked how does it know which info it is for.Hope it is clear
If you would model your relations correctly, you don't have that problem.
You would have to define a foreign key in the 2nd table, and the foreign key would have to refer to the primary key (or at least some other uniquely indexed field or combination of fields) in the 1st table. If you plan on using dish_name as a foreign key in the 2nd table, that would necessarily mean that dish_name would have to be unique in the 1st table.
This is probably a bad idea, so it's better to create a dish_id foreign key column in your 2nd table and get rid of the dish_name column.
I have the following table
title year authors
--------------------------------------------------------------------------
title book 1 2015-12-01 White McGregor Waine
title book 2 2016-10-14 McGregor Bush Rossi
title book 3 2017-05-22 Bush McGregor Lopes
...... .... .......
Authors field is composed of names separated by a white-space (I might also use a different separation character, if needed).
How do I extrapolate a desc list of authors who published more books? Consider I don't know the names of authors.
In the example the list is:
Author Books published
---------------------------------------
McGregor 3
Bush 2
Whaite 1
Whaine 1
Rossi 1
Lopes 1
The apt way to do this is to normalize.
This falls under many to many relationship.
For storing many-to-many relationships, an intermediate table that mainly stores the primary keys (IDs) of each relationship is required. In your case,
authors_table(author_id, name,...)
books_table(book_id, name,...)
authors_books_table(id, author_id, book_id)
Here is a more elaborate explanation.
This followed by a simple join, will get you the desired result.
First You have to learn Normalization. Database normalization, or simply normalization, is the process of organizing the columns (attributes) and tables (relations) of a relational database to reduce data redundancy and improve data integrity. ... Informally, a relational database relation is often described as "normalized" if it meets third normal form.
You can Also Try With this
<?php
$myarr = "White McGregor Waine";
$myarr = explode(" ",$myarr);
foreach($myarr as $value){
$sql = "SEECT title FROM table where authors = '$value'";
echo $sql;
}
As already pointed out by others, you will need to normalize your database. The advantages of normalization include but do not limit to the following:
you will have an easier time finding the data you are interested in, in your case you will be able to find the authors in a given table and the relations in an intermediary table instead of handling varchars using white space
your database will be consistent, that is, you will be able to easily handle CRUD operations with your authors, for example if you change the name of an author in the authors table, it will be changed for all places the author is referenced at. Also, you will be able to differentiate authors with the same name
you will not have redundant data stored, increasing the size of the data you have
You will therefore have the following tables:
authors(id, name)
author_of_book(id, author_id, book_id)
books(id, title, year)
Make sure the id fields are primary keys and author_id and book_id, respectively are foreign keys.
With this new structure you will be able to do the selection you want like this:
select authors.name, count(*) as `books published`
from authors
join author_of_books
on authors.id = author_of_books.author_id
join books
on author_of_books.book_id = books.id
group by authors.id, authors.name
order by count(*) desc
Lately i found myself designing a database. The database is consisted of several tables (InnoDB) :
Table 1: Country (id , country_name)
Table 2: City (id, city_name , countryid)
Table 3: Users (id , cityid , A , B, C, D, E)
On the Users table, A , B ,C , D and E are some characteristics of the user, where characteristic A if you combine it with cityid must be unique, that is why i created a unique index for these 2 columns:
CREATE UNIQUE INDEX idx_user ON Users(cityid , A);
The rest columns B,C,D and E are other user characteristics (for example hair color, height, weight, etc.), that as you understand, will be repeated on the table ( hair color = black, or weight = 75 kg).
At the same time countryid and cityid are configured as foreign keys on UPDATE and DELETE CASCADE.
Search will be based on cityid and A columns. A drop down menu to select the city (hence cityid) and a text box to insert the characteristic A and then hit SEARCH button.
My questions are:
On Users table, i have repeating data in the same column (columns B, C ,D and E). This is against 2NF. Do i have to create a separate table for each of these columns and then assign a foreign key of each of these tables to Users table in order to achieve 2NF?
Table B (id, Bchar)
Table C (id, Cchar)
Table D (id, Dchar)
Table E (id, Echar)
Users (id, cityid, A, Bid, Cid, Did, Eid)
For the time i will not use columns B,C,D and E as search data, only display them after searching using cityid and A search. If (in the future) i decide that i need to display all results of Users that live in cityid and have black hair, what do i have to keep in mind now while designing the database?
In one hand we have DML(INSERT, UPDATE, DELETE) and on the other hand quering (SELECT). DML will work faster on normalized DBs and quering on denormalized DBs. Is there a middle solution?
Will UNIQUE INDEX created above , be enough to ensure uniqueness for the combination of the data in columns cityid and A? Do i need to further restrict it using JavaScript or better PHP?
Multiple Queries VS Joins:
Normalizing the database will require multiple queries or a single query with joins. In the case where "The user searches for a user from Madrid with characteristic A":
a) Multiple queries:
i) Go to City table and find the id of Madrid (for example, id = 2 )
ii) Given the Madrid id and the input for characteristic A, go to Users table and SELECT * FROM Users WHERE cityid="2" AND A="characteristic";
b) INNER JOIN:
i) SELECT City.city_name, Users.B, Users.C FROM City INNER JOIN Users ON Users.cityid = City.id;
Which one should i prefer?
Thanks in advance.
Your tables are already in 2NF.The condition for 2NF is there should be no partial dependency.For example lets take your users table and user-id is the primary key and another primary key more appropriate to call candidate key is (cityid,A) with which you can uniquely represent a row in the table.Your table is not in 2NF if cityid or A alone is enough to uniquely retrieve B,C,D or E but in your case one needs both (cityid,A) to retrieve a unique record and hence it's already normalized.
Note:
Your tables are not in 3NF.The condition for 3NF is no transitive dependency.Let's take the users table here userid is the primary key and you can get a unique (cityid,A) pair with that and in turn you can get a unique (B,C,D,E) record with (cityid,A) obtained from userid.In short if A->B and B->C indirectly A->C which is called transitive dependency and it's present in your user table and hence it's not a suitable candidate for 3NF.
I'm in the situation where my client e-mails me an excel-file with 50 columns of data extremely un-normalized. I then export it to CSV and upload into MySQL -- single table. The columns are for different ingredients (10 columns of data for each ingredient -- title, category, etc) and then 40 different columns for characteristics on each ingredients. So each ingredient in the table has all of these 50 columns even though every column doesn't apply for that ingredient.
My question is if I can create a SQL that selects only filled in characteristics for one selected ingredient and leaves out all of the other columns?
(I know that another option is to build my own CSV-parser that created multiple tables and then write SQL for them instead, but I wanna investigate solving this as is first. If that's not possible then I just have to face that and build a parser ;P)
This is as far as I came but this doesn't completely exclude columns not filled in (or that contains "nei".
SELECT
IF(`Heving-vanlig-gjaerbakst` <> '' AND `Heving-vanlig-gjaerbakst` <> 'nei', `Heving-vanlig-gjaerbakst`, 'random') AS `test1`,
IF(`Frys-kort` <> '' AND `Frys-kort` <> 'nei', `Frys-kort`, 'random') AS `test2`
... and for the 38 other rows ...
FROM x
WHERE id = 123
And I'd rather not solve this in the PHP-code by skipping empty rows =P
Example row (column names first):
g1 gruppe ug1 undergruppe artnr artikkel beskrivelse status enhet ansvar prisliste Heving-vanlig-gjaerbakst Heving-soete-deiger Deig-stabilitet Smaksgiver Saftighet Krumme-poring Skorpe Volum Konservering Skjaerbarhet Frys-lang Frys-kort Kjoel Holdbarhet E-fri Azo-fri Mandler Aprikoskjerner Helmiks Halvmiks Base Konsentrat Utstrykning Bakefasthet Frukt-Baerinnhold Slippegenskaper Hindre-koksing Palmefri Fritering Smidighet Baking Kreming Roere Fylning Dekor Prefert Viskositet Cacaoinnhold Fet-innhold
100150 Bakehjelpemidler 100150200 Fiber/potetprodukter 10085 Potetflakes sekk 15 kg Egnet til lomper, lefser, brød og annet bakverk. B... Handel Sekk Trond Olsen JA xxx xxx xxx
As you can see most columns are empty here. X, XX and XXX is a form of grade-system, but for some columns the content is instead "yes" or "no".
And as I said, the first 10 columns are information about that product, the other 40 is different characteristics (and it's those I wanna work with for one given product).
It sounds a bit as if you'd like to convert the table you have into two tables:
CREATE TABLE Ingredients
(
g1 ...,
gruppe ...,
ug1 ...,
undergruppe ...,
artnr ... PRIMARY KEY,
artikkel ...,
beskrivelse ...,
status ...,
enhet ...,
ansvar ...,
prisliste ...
);
I've opted to guess that the artnr is the primary key, but adapt what follows to the actual primary key. This table contains the eleven (though your question said ten) columns that are common to all ingredients. You then have another table which contains:
CREATE TABLE IngredientProperties
(
artnr ... NOT NULL REFERENCES Ingredients,
property VARCHAR(32) NOT NULL,
value VARCHAR(3) NOT NULL,
PRIMARY KEY(artnr, property)
);
You can then load the populated columns from your original table into these two. At worst, there'd be 40 entries in IngredientProperties for one entry in Ingredient. You might make 'property' into a foreign key reference to a defining list of possible ingredient properties (a third table that defines the possible values for the properties - basically, a record of the column names from your original table). If you add the third table, it might logically be called IngredientProperties (too), in which case the table I called IngredientProperties needs to be renamed.
You can then join Ingredients and IngredientProperties to get the information you want.
I'm not sure that I recommend this solution; it is basically a use of the 'Entity Attribute Value' approach to database design. However, for extremely sparse information like you seem to have, and when used with the constraint of the third table.
What you can't sensibly do is handle all possible combinations of 40 columns as that number grows exponentially with the number of columns (and is pretty large with N = 40).
I'm creating an auction style website where users can bid for items. I've into a bit of confusion regarding the database design when it comes down to projects and bidding features. Initially I thought a table called 'project' could contain a multiple-valued column called 'bids' containing bid_id's.. However after a bit of research it appears this method is a no-no.. But I'm sure I can remember a lecture or two from university that mentioned multi-valued columns in database designs. What would be the best approach for the problem?
Thanks
Dan
It depends on your requirements on how to design the database. If you have exactly one auction per product ID, a BID table may be enough. If each auction requires individual configurations you may end up with an AUCTION table as well:
The product table
PRODUCT
PRODUCT_ID -- primary key
....
Auction table
AUCTION
AUCTION_ID -- PK
PRODUCT_ID -- foreign key to PRODUCT
START_TIME
END_TIME
MODE -- e.g. dutch, english...
...
Bid table
BID
BID_ID -- PK
AUCTION_ID -- foreign key to AUCTION
AMOUNT
TIME
...
In general, you should avoid multi-valued columns in a relational database model. You should aim for normalization. If it later comes to query optimization you may need to introduce further indexes, views and/or procedures.
In my opinion, the best solution would be to have a table bids containing all the necessary information in columns, for example: bid_id, product_id, bid_amount, bid_time, etc.
this is only meta-sql, you know.
users: id, ...
bids: id, auction_id, user_id, amount,
auctions: id, object, ... end-date, ...
indexes on bids: auction_id, amount desc
(among others like id's, names ...)