0

I have a schema for a scorekeeping database with Game, Team, Player tables.

One team has many players, each player has only one team. Each team plays many games, each game has many teams. In each game, players score a certain number points individually and as a team - this maps to a player_score and a team_score. A team's total score for a game is the sum of all of its players player_score for that game and the team's team_score for that game.

This is my plan -

GameTeam table includes the team's team_score for that game, and has foreign keys of Game.id and Team.id. Many to many.

GamePlayer table includes the player's player_score for that game, and has foreign keys of Game.id and Player.id. Many to many.

So the problem is that GameTeam and GamePlayer aren't linked and it seems like they should be - since a player always belongs to one team. My solution was to add a one-to-many relationship between GameTeam and GamePlayer, then if I have a game id and a team id I can search for a GameTeam where those match, iterate over all the gameTeam.gamePlayers adding each player_score, add on the team_score at the end, and calculate total_score.

Does this make sense? Am I completely off? Any help appreciated, thanks. If it matters, I'm using SQLAlchemy.

philipxy
  • 14,867
  • 6
  • 39
  • 83
quantumtremor
  • 3,787
  • 2
  • 17
  • 20
  • For me it's fine. Any problems with the structure? I would also suggest to add an image of your DB relations to the question to let us easier understand current structure. Or it's even better to add sql fiddle. – StanislavL Nov 26 '14 at 06:24
  • Well it seems awkward that Game has attribute of game_teams AND game_players, when game_players belongs to game_team right? Does that matter? The alternative would be just a many to many mapping from MatchTeam and Player, which would be 3 foreign keys (a joint of match id and team id from MatchTeam, and player id) – quantumtremor Nov 26 '14 at 06:41
  • Do you really need a relationship between `GameTeam` and `GamePlayer`? It seems to me that this relationship can be inferred from the fact that they share the same `Game` (having same `Game.id`), and players belong to just one `Team`. Or am I missing something? However if the player switches team, my assumption would not be something to count on, and it might effectively invalidate previous games. – van Nov 26 '14 at 08:45
  • They can't switch teams. I just thought there should be a relationship because they do in real life. So to get a team's total score, say, I would do (pseudocode) for each gameTeam in round.gameTeams { sum = gameTeam.team_score; for each gamePlayer in round.gamePlayers { if (gamePlayer.player.team.id == gameTeam.team.id) { sum += gamePlayer.player_score }}} Does this make sense? The other way seems cleaner though, if I don't have to cross check team_ids and I can assume some set of GamePlayers belong to a GameTeam. – quantumtremor Nov 26 '14 at 09:45
  • This is not a "normalization", it is a(n incomplete) "design". – philipxy Nov 27 '14 at 05:13

2 Answers2

1

The problem to your design is that you have used surrogate identifier as the primary key for the tables, a well defined primary key will solve the problem:

Team   -> pk:team_id
Player -> pk:player_id
TeamPlayer -> pk:{team_id + player_id}

Game   -> pk:game_id
GameTeam -> pk:{game_id + team_id}
GamePlayer -> pk:{game_id + GameTeam_pk + TeamPlayer_pk} 
              = {game_id + {game_id + team_id} + {team_id + player_id} }

Having check constraints on GamePlayer will help the problem:

GamePlayer 
{
 Check game_id (FK of Game) = game_id (FK of GameTeam );
 Check team_id (FK of GameTeam) = team_id (FK of TeamPlayer);
}

So
player_score will be property of GamePlayer.
team_score will (may) be SUM of GamePlayer.player_score with specific team_id.

Community
  • 1
  • 1
Mohsen Heydari
  • 7,256
  • 4
  • 31
  • 46
  • Why is there a TeamPlayer table if Team to Player is a one to many relationship? – quantumtremor Nov 28 '14 at 02:15
  • Does it make sense to do a many-to-many with GameTeam and Player? By well-defined primary key do you mean composite key? – quantumtremor Nov 28 '14 at 02:25
  • Yes. I mean composite keys. If Player definition is separated from Team defecation, so you will need an association table between them. This will give you the facility that players can be assigned to deferment teams during time. – Mohsen Heydari Nov 28 '14 at 07:52
  • Existence of TeamPlayer table is dependent to you business logic. – Mohsen Heydari Nov 28 '14 at 08:01
0

Identify the apparently basic application relationships you are interested in. Eg:

Team "[team_id] identifies a team"
Player "[player_id] identifies a player"
GameTeam "[game_id] identifies a game involving team [team_id]"
TeamPlayer "player [player_id] plays for team [team_id]"
GamePlayer "in game [game_id] player [player_id] scored [player_score]"

Then make a table for each such relationship. A table holds the rows whose values participate in its relationship, ie that are so related. Ie it holds the rows that satify the parameterized statement (predicate) of a relationship, ie that make its parameterized statement into a true statement (proposition).

Now tables calculated by table operators satisfy relationships built by corresponding logical operaters. An INNER JOIN holds rows that satisfy the AND of its operands' relationships. For a UNION, the OR. WHERE and ON both AND in conditions. SELECTing out column C from a table with predicate "...[C]..." gives the relationship "THERE EXISTS a value for C such that ...[C]...".

"Linking" is irrelevant. A "link" is a foreign key. A FK is irrelevant to querying other than telling you that if you INNER JOIN then you only get one row from the target table per row of the source table. If there's no "link" you can still INNER JOIN for the relationship that is the AND of the operands' relationships, you just might get more than one row from the target table matching per row of the source table. (The FK tells you that IF THERE EXIST values for source columns such that source relationship THEN THERE EXIST values for target columns such that target relationship.) (Which is not a "relationship" but a fact.) Similary, regarding shared columns and INNER JOIN, SQL always conceptually initially produces a cross product for INNER JOIN of which some rows meet the given conditions. Links between columns and common columns are irrelevant. Just identify what relationship is represented by a base table or query table.

("A p:q relationship" is some particular relationship that happens to be p:q. You can't talk about its cardinality until you identify what "it" is.)

Then you have to determine base relationships/tables that are sufficient for expressing everything relevant about your application, ie suffient for expressing every relevant query relationship/table. The particular choices are what design is all about. (This will involve among other things normalization, which is about replacing relationships/tables of the form "... AND ..." by two or more of the ANDed relationships/tables. Although there isn't any normalization in your question or this answer.)

philipxy
  • 14,867
  • 6
  • 39
  • 83