|
|
|
| |||||||||
![]() |
|
|
«
Previous Thread
|
Next Thread
»
|
Thread Tools | Search this Thread | Rate Thread | Display Modes |
|
#1
|
||||
|
||||
|
relational database design
OK, I'm TRYING to figure out this relational database crap but it's wrackin' mah bwain. I want to store multiple genres for a game and am having trouble coming up with the most efficient solution.
Do I, like I've been attempting, have to use a genreID "set" type in the "compare" table in order to assign multiple genres to a game--or must I list gameID twice, which would end up duplicating other data?: table: compare fields (data): id, gameID, genreID ("set" type) sample data: 1, 1, (1,2) table: genres fields: genreID, genre sample data: 1, action 2, adventure Or do I list games with multiple genres in the genres table (which still duplicates gameIDs but takes up less space than in the compare table)?: fields: genreID, gameID, action, adventure, role-playing, simulation, strategy sample data: 1, 1, action 2, 1, adventure Help! Last edited by Eepē : October 1st, 2002 at 11:53 PM. |
|
#2
|
||||
|
||||
|
Well, to completely normalize it, you would want three tables.
One would be your game table, where the game is assigned an ID and you store whatever kind of information on it. game_id would be unique in this table. The next is a genre_type type, where you define the possible types of genres. genre_id would be unique in this table. The third is just a two column table that relates game_id to genre_id. If a game has multiple genres, then you list that game_id twice. Make a multiple key on both columns, so you can't have the same game_id - genre_id listed twice in the table w/o throwing an error. Does that make sense? ---John Holmes... |
|
#3
|
||||
|
||||
|
No, it doesn't. What do you mean by "multiple key"? I only know of 2 key types: "primary" and "foreign".
And what do you mean when you say "The next is a genre_type type, where you define the possible types of genres."? List how, as the 1st or 2nd example I originally gave? Sounds like you're attempting to describe example 2 but I'm not sure. Either way it looks like data is repeated and the data isn't normalized. :/ At least with example 1 there is LESS repeated data since not all games will be in multiple genres and ONLY the genres they're in will be in the genreID field. I just don't get it. ![]() |
|
#4
|
|||
|
|||
|
I definitely wouldn't go with your second scenario. You waste fields that will never be used and will later cause you to have to run ALTERS when you want to add genres. Don't worry about trying to save space by packing all your data into one table. Disk space is cheap, good design takes time in the beginning, but pays back later on when it comes time to maintain your database and application code.
As Sepodati said, separating into multiple tables is your best bet. That's where relational databases shine, in being able to relate data from more than one table. This sort of design is the most flexible and allows you to expand your application in the future without having to go back and modify the database schema. Don |
|
#5
|
||||
|
||||
|
And, thus, we're back to my original question: which multiple-table way do I use and how are those tables designed?
I need explicitly detailed table setups please... |
|
#6
|
||||
|
||||
|
From what you've described, Sepodatis suggestion seems to be what you need.
Have a look at this, as I think it's pretty self-explanatory Code:
mysql> CREATE TABLE games (
-> game_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> game_name VARCHAR(150) NOT NULL);
Query OK, 0 rows affected (0.03 sec)
mysql> CREATE TABLE genres (
-> genre_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> genre_name VARCHAR(100) NOT NULL);
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE relation (
-> game_id INT NOT NULL,
-> genre_id INT NOT NULL,
-> UNIQUE KEY(game_id, genre_id));
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO games (game_name) VALUES ('Unreal Tournament'),('FIFA 2002'),('Grand Theft Auto III');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> INSERT INTO genres (genre_name) VALUES ('Action'),('Adventure'),('Role-playing'),('Simulation'),('Strategy'),('Sports');
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> INSERT INTO relation VALUES (1,1),(3,1),(2,6),(3,2);
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM relation;
+---------+----------+
| game_id | genre_id |
+---------+----------+
| 1 | 1 |
| 2 | 6 |
| 3 | 1 |
| 3 | 2 |
+---------+----------+
4 rows in set (0.00 sec)
mysql> SELECT a.game_name, b.genre_name FROM games a INNER JOIN relation r USING (game_id) INNER JOIN genres b USING (genre_id);
+----------------------+------------+
| game_name | genre_name |
+----------------------+------------+
| Unreal Tournament | Action |
| Grand Theft Auto III | Action |
| FIFA 2002 | Sports |
| Grand Theft Auto III | Adventure |
+----------------------+------------+
4 rows in set (0.00 sec)
mysql> SELECT b.genre_name, COUNT(a.game_id) AS howmany FROM genres b LEFT JOIN relation r USING (genre_id) LEFT JOIN games a USING (game_id) GROUP BY b.genre_name;
+--------------+---------+
| genre_name | howmany |
+--------------+---------+
| Action | 2 |
| Adventure | 1 |
| Role-playing | 0 |
| Simulation | 0 |
| Sports | 1 |
| Strategy | 0 |
+--------------+---------+
6 rows in set (0.00 sec)
Just as an example, in which the games/genres might not be exactly as you want them. Feel free to adapt it... ![]() //NoXcuz
__________________
UN*X is sexy! who | grep -i blonde | date; cd ~; unzip; touch; strip; finger; mount; gasp; yes; uptime; umount; sleep |
|
#7
|
||||
|
||||
|
OK, thanks for the detailed setup, NoX, but how would I go about letting people add genres in addition to the present ones? If you look at the game form I want to use for submissions, you can see there are a LOT of text-entry fields for checkboxes and other options (some pull-down lists). I want people to be able to add comments and/or more detail to the options to elaborate on them (since not all games will have the same exact features, effects, etc).
How best do I design the addition of custom fields to go along with the provided options? |
|
#8
|
||||
|
||||
|
Wow...that's a lot of data. I think you should break it up into a "wizard" of types, and make it multiple pages to submit the review. It would be less confusing and daunting to the user, I think.
As for adding genres and the like, you already have a text box option instead of a checkbox. If they user enters something in the text box, then make this a new genre, and insert it into the genre table. You might want to make it so you "approve" them or something, so it doesn't get filled up with worthless genres. Making it a wizard and seperating it out will make for less queries and HTML per page, so you can explain things more and add genres with no problem. ---John Holmes... |
|
#9
|
||||
|
||||
|
Yea, I'm already planning to separate the form into multiple pages (as is already stated in the form's introdiction).
However, I'm not sure how to design it for the rest of the text-entry fields. Do I have to have a bajillion cross-reference tables with a custom text-entry field in EACH one?So, for the "engine" category: table: engine_names fields: id, name table: engine_types fields: id, type data: 1, polygon 2, voxel 3, NURBS table: engines fields: id, nameID, websiteID, modified (0,1 set), developerID, typeID Now, do I put both custom engine type and engine name fields in a single cross-reference table like this: table: games_engines fields: id, gameID, engineID, engineNameID, engineTypeID or do I have to make separate cross-reference tables for engine name AND engine type: table: games_engineNames fields: id, gameID, engine_nameID table: games_engineTypes fields: id, gameID, engine_typeID or do I use the engine: table: engines_names fields: id, engineID, engine_nameID table: engines_types fields: id, engineID, engine_typeID At this rate I'll have a gazillion cross-reference tables! Ugh... |
|
#10
|
||||
|
||||
|
You could probably have just one table for all of these "types".
You'd have an ID column, a type column that was game, engine, genre, etc, and then a value column. So, if you wanted all the possible genres, you'd just do SELECT value FROM table WHERE type = 'genre'; Same for engine and game types, etc. This would save you from having a ton of tables and even though you may have some repeated data, it would be easier to work with. You can "over-normalize" a table.... ---John Holmes... |
|
#11
|
||||
|
||||
|
What do you mean by "types", engine types or something else? I don't understand. Can you be more specific? Thanks.
|
|
#12
|
||||
|
||||
|
Well, I don't really understand, either.
![]() I'm talking about all of your questions that are checkboxes, where you are talking about genre, engine_type, engine_optimization, smoke, dust, etc... Instead of having a seperate table for each of these, have a single table where the "type" column would be what I listed above. So, for genres of Action, Role-Playing, Strategy, and Adventure, you'd have four rows in your table. 1,genre,Action 2,genre,Role-Playing 3,genre,Strategy 4,genre,Adventure And you'd add to the same table for your engine types. 5,engine_type,Polygon 6,engine_type,Voxel 7,engine_type,NURBS etc... Then it would be easy to get all of the values for a specific type and to add/delete from the types. Does that clear it up? It's confusing when you're working with that much data. Oh, and for storing the data, you could do the same thing. If I check genre for a certain game, then you have another table that stores my choices that would have game_id (what I'm rating/evaluating), type (again, genre or engine, or smoke...), and the value I chose. If I choose four values, then I have four rows. It would be easy to select out statistics out of a table like that, too, rather than 20 different tables... ---John Holmes... ---John Holmes... |
|
#13
|
||||
|
||||
|
That seems VERY wasteful. At the very lest the "type" (category) could reference a separate "category" table:
table: categories fields: id, category data: 1, genre 2, engine_type But this doesn't seem any less confusing than having multiple tables, which actually seems LESS confusing since the data is separate and relational. Perhaps I should just allow duplicate fields for most things since it's obviously turning out to be a bitch to try and make it all relational. :/ Or do you perhaps mean a separate table for all the "other" types (text-entry fields): table: games_other fields: gameID, type, other data: 1, genre, driving 2, publisher, New Publisher 3, developer, New Developer 4, engine_name, New Engine 5, engine_type, holographics That might work...and it would only hold the exact amount of "other" fields per game instead of having lots of null/blank values in each cross-reference table. Last edited by Eepē : October 11th, 2002 at 02:36 PM. |
|
#14
|
||||
|
||||
|
Hey...it's just my opinion. Yes, the "type" column should reference another table that way you don't repeat that data.
It's basically the same as having a seperate table for each "type", genre_table, engine_table, dust_table, etc, but having it all together will make things easier in my opinion. You wouldn't have to manage all of those seperate tables. And, if someone submitted an "other" entry, like "Adult" for genre types, the next time your form is created, you just do a SELECT value FROM table WHERE type=1 (where 1 = "genre") and "Adult" would now be a checkbox instead of the user having to type it in. You could even regulate this by having an "approved" column that would say whether the value should show up as a text box or not. Again, yes, you could do this with seperate tables for each one, but I think it would be more work and more room for error. ---John Holmes... |
|
#15
|
||||
|
||||
|
OK, I'm STILL not sure how to store checkboxes and text-entry fields as I have them laid out in the game submission form at http://tnlc.com/eep/compare/gameform.html . I would VERY MUCH appreciate any help (the more people the better) in how best to design the tables for this database. Here is what I've come up with so far:
1. a single cross-reference table that holds the IDs of most other tables in a heirarchial structure (see http://tnlc.com/eep/compare/relations.jpg) 2. multiple games_whatever (genre, publisher, developer, engine, etc) cross-reference tables (see http://tnlc.com/eep/compare/relations3.gif - disregard the duplicate websiteID fields) 3. same as 2 except adding the text-entry fields in the cross-reference tables (see http://tnlc.com/eep/compare/relations4.gif - only "genres" table has this) 4. same as 2 except the cross-reference tables consist of id, gameID, and each column of the table's contents instead of just listing the contents in a single column as in the previous examples) - for example: table: games fields: id, name data: 1, Tomb Raider 2, Tomb Raider II ... table: games_genres fields: id, gameID, action, adventure, role-playing, simulation, strategy, other data: 1, 1, 1, 1, null, null, null, null 2, 2, 1, 1, null, null, null, null ... This allows only adding the appropriate genres to each game without having to duplicate gameID keys in "normal" cross-reference tables: table: games_genres fields: id, gameID, genreID data: 1, 1, 1 2, 1, 2 3, 2, 1 4, 2, 2 ... Is #4 the best, most efficient way to do this or must I use the wasteful duplicate-key design? I want to allow game submitters to enter new fields into the various tables via text-entry fields (which I validate) so I need some way of storing them (and turning them into checkboxes) but I'm not sure how to design this either. Also, not all text-entry fields will be added as new checkboxes (particularly if the feature is VERY unique/specific to the game). Thanks for any assistance! |
![]() |
| Viewing: Dev Shed Forums > Databases > MySQL Help > relational database design |
| Thread Tools | Search this Thread |
| Display Modes | Rate This Thread |
|
|
|
|
|