tags:

views:

83

answers:

3

I am creating a database that tracks replays for a game. Each replay has a different game mode that is either team-based gameplay or individual-based gameplay. Depending on the game mode, I want to record the winning team or the winning individual.

I have the following MySQL table that tracks rounds in the replay and the associated winner:

CREATE TABLE replay_rounds (
    replay_id INT UNSIGNED NOT NULL,
    round SMALLINT UNSIGNED NOT NULL,
    winning_player_id INT UNSIGNED,
    winning_team_id TINYINT UNSIGNED,
    FOREIGN KEY (replay_id) REFERENCES replays(id),
    FOREIGN KEY (replay_id, winning_player_id) REFERENCES replay_players(replay_id, player_id),
    FOREIGN KEY (winning_team_id) REFERENCES teams(id),
    PRIMARY KEY (replay_id, round))
CHARACTER SET=utf8
COLLATE=utf8_general_ci
ENGINE=InnoDB;

Using what I have now, if the game mode is team-based then I will set the winning_team_id for each round and set the winning_player_id to null. Likewise, if the game mode is individual-based, I will set the winning_team_id to null.

Performance-wise and in terms of best practice, is it all right to leave it like this? Is there a compelling reason to split this into a separate table for each game mode (even if there's only two modes)? How about a hypothetical situation where game modes are constantly being added -- would this be best resolved by creating a table for every new game mode?

+1  A: 

I would just have one winning_id (drop the individual winning ids for team and player) and an additional attribute for game_type_cd. This will be a lookup attribute that is a foreign key to a new table called GAME_TYPE_COES. Then all you need to do is fill in the winning_id and the game type. This will allow for an infinite amount of game types with only having to add data to the GAME_TYPE_CODEs table and not having to change the data structure.

northpole
This would work if the winning_id has the same type for each game mode. In my example, winning_id is a TINYINT if it's a team, and winning_id is an INT if it's an individual. I could just choose INT since it's a superset of TINYINT, but that seems like a coincidence/hack.
Kai
I think your "hack" would be a okay choice here in order to normalize the database.
northpole
Point well taken :) I need to learn to be less of a perfectionist and apply specific solutions to problems.
Kai
however, that being said. Can you change the data type/structure of your ids to be consistent?
northpole
What is inconsistent about my ids?Additionally, I haven't mentioned, but there is a table for game_types and each replay references a game_type_id, so I can just follow the replay_id for a specific round to find out its game_type.
Kai
yes, sorry, got a bit off track there, your keys are consistent.
northpole
Ah I just thought of another issue with this approach. If I combine the fields into one winner_id then I'll have to remove the FOREIGN KEY constraint for winning_player_id and winning_team_id, meaning the database can't enforce that these players/teams are actually in the replay. How does that downside weigh in, in your opinion?
Kai
If it was me, I would probably look at why you need two separate tables for player and team. I would try to re factor those into a single (possibly more normalized) structure that would allow for one foreign key. If that is not a possibility, you will indeed have issues with enforcing the data integrity. Not that it can't be done through things like functions, it will just require more custom work.
northpole
A: 

I think this database should be relational - Perhaps 1 table for the (person/team-id), then another that denotes gameid/(team/person-id)/win, then another that has ID/replayinfo/etcetc

So..

TeamID | Name
-------------
  1    | Thunderbirds
  2    | John Petravich

GameID | TeamID | Win?
-----------------------
   1   |    1   |  1
   2   |    2   |  0

ReplayID | GameID | (Your table's other properties)
----------------------------------
    1    |    1   | etc

Now you can use the relationship to determine all of the different information about a particular team or individual. If you need to tailor pages based on what kind of thing they are, add a type column to the first table and display your pages based on that type id.

$.02

C Bauer
A: 

I'd suggest to read WP: Database normalization. Especially the Normal Forms are worth knowing about when discussing about splitting/unifying tables...

Johannes Weiß