Is this normalization correct? (two many-to-manys connected by a many-to-one)

前端 未结 2 487
没有蜡笔的小新
没有蜡笔的小新 2020-12-20 10:17

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

One team has many players, each player has only on

相关标签:
2条回答
  • 2020-12-20 10:39

    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.

    0 讨论(0)
  • 2020-12-20 10:43

    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.)

    0 讨论(0)
提交回复
热议问题