如何在sql中设计M-M表之间的关系

时间:2012-10-12 04:23:38

标签: sql database-design

如果我有一个match table ( id , details)team table (id,name),我希望得到两支队伍的所有比赛。

我的解决方案是:

(match_id,team1_id,team2_id)

上创建第三个表格

这是这种情况下的最佳做法吗?

2 个答案:

答案 0 :(得分:2)

您不需要第三个表 - 直接从match表中引用团队:

enter image description here

只是为了澄清,{team1_id, team2_id}应该是一个关键,允许同一对团队参与多个匹配。当然,不用说你需要适当的FK和CHECK(team1_id <> team2_id)

要获得给定团队的比赛,您需要..

SELECT ... WHERE team1_id = :given_team_id OR team2_id = :given_team_id

...所以你需要两个团队ID的索引,如上图中的I1I2所示。

另外,考虑到性能原因,请考虑使这些索引更宽。例如,如果您只获取有限的字段子集......

SELECT team1_id, team2_id FROM ...

...并将索引扩展到cover这些字段(I1: {team1_id, team2_id}I2: {team2_id, team1_id}),DBMS根本不需要触及您的表堆来满足查询。


或者,您可以考虑使用自然键,例如:

enter image description here

这将允许你消除其中一个索引(代理PK下的那个索引:{match_id}),但当然会使任何下游FK“更胖”,may or may not是一件好事取决于你想要完成的事情。

根据您的查询需求,您可能会调整PK字段的顺序:

  • 例如,如果您的大多数查询都询问:“给我最近X天播放的比赛”,请考虑将match_date移到前面。
  • 如果您的大多数查询都要求随时播放比赛,请将其保留在后面。
  • 如果两者都有,那么你需要一个额外的索引。

顺便说一句,拥有第三张牌{match_id, team_id}适用于两支以上球队可以比赛的比赛(例如帆船比赛)。它还有一个令人遗憾的特点,即只允许一个甚至零个团队 - 这是你可能需要以非声明的方式防范的。

上面的设计确保了正好有两个团队。

答案 1 :(得分:1)

假设匹配只能由两个表播放,team1_id和team2_id应该作为属性match表本身的一部分。不需要单独的表格。您还可以在team1_id和team table的id之间定义FOREIGN KEY关系,同样也为team2_id定义。

对于可以由多个团队进行的匹配,需要第三个表格,在这种情况下,表格结构将是(match_idteam_id),其中将有多个记录具有相同的match_id,即match table和match_teams表之间的一对多关系。