记录一个运动队的比赛-多对多关系?

5
我是Ruby on Rails的新手,但之前创建过一些简单的应用程序。现在我正在做一些更复杂的事情,而且在数据库设计方面遇到了困难。
我正在创建一个运动联赛管理器,并需要一些关于如何建立团队和比赛之间关系的建议,以指引我朝正确的方向前进。每当两个团队之间进行比赛时,比赛就会被记录下来。我想能够做到以下几点:
1)在特定团队的页面上,我想显示该团队参加的比赛列表。
2)我想记录每个团队的胜负平,并在联赛积分榜上显示。
对于第一点,我认为这将是多对多的关系,即一个团队有多个比赛,一个比赛有多个团队(实际上只有两个)。我有点困惑的是如何以及在哪里存储每个团队的统计数据。我把胜利/失败/平局放在团队表中吗?如果是这样,如果我要有一个显示每个团队胜利/失败/平局的页面,我该如何获取这些信息?

我正在考虑这个问题,很快就会发布答案。这绝对是一个有趣的案例,因为虽然表面上你确实有一个多对多的关系,但它并不真正符合模式。我认为有理由使用中介表。 - coreyward
1
如果您记录每场比赛的结果,那么胜利/失败/平局已经隐含在您的数据库中,因此您可能不需要显式地存储该数据,因为您可以根据需要重新计算它。 - jswolf19
4个回答

4

这并没有完全完成,但也许能帮到你或其他人在这方面开始行动。

我专注于如何构建团队和比赛之间的关系结构。我相信解决方案的一部分在于使用多态关联,另一部分可能是自连接。我发誓它就在我的眼前,但我没看到。

在这里,我们先迈出小步,假设您的比赛表格如下所示...

  id   |   home_team_id  |  away_team_id  |  home_team_score  |  away_team_score

您可以通过以下关联在您的模型中设置:

class Match
  belongs_to :home_team, :class_name => :team
  belongs_to :away_team, :class_name => :team
end

class Team
  has_many :home_matches, :foreign_key => :home_team_id, :class_name => :matches
  has_many :away_matches, :foreign_key => :away_team_id, :class_name => :matches
end

明显的问题是有两个关系,实际上应该只有一个。这就是为什么我认为多态关联可以帮助解决问题,但这有点复杂。
请参阅Rails指南中的多态关联,看看是否能帮助你理解我无法理解的内容。

0
我认为可以使用以下方式完成。
class Team < ActiveRecord::Base
    has_many :games
    has_many :matches,:through => :games
end

class Matche < ActiveRecord::Base
    has_many :games
    has_many :teams,:through => :games
end

class Game < ActiveRecord::Base
    belongs_to :team
    belongs_to :match
end

如果您需要查找任何团队的总比赛次数,则

= team.games.count

如果您需要查找任何团队赢得的总比赛数,则
= team.games.where(:winner => true).count

0

我建议不要在这里创建传统的多对多关系。相反,您只需要两个表:TeamsMatches

每个团队都将在Teams中通过一行进行标识,并具有唯一标识符,例如TeamId

Matches表将具有以下列:

  • MatchId - 一个合成主键
  • SeasonId - 标识比赛所在的赛季
  • HomeTeamId - 主队
  • VisitngTeamId - 客队
  • HomeTeamScore
  • VisitngTeamScore
  • ... 您想为单个比赛保留的任何其他统计信息

我假设您已经了解主队和客队的概念。如果没有,您可以将这些列命名为Team1IdTeam2Id或类似的名称。

我有点困惑的是如何以及在哪里存储每个团队的统计数据。我应该把胜利/失败/平局放在哪里?
胜利、失败和平局都隐含在“比赛”表中 - 您可以查询该表以获取团队的记录。例如,以下查询返回X队的胜利、失败和平局:
-- Wins
SELECT COUNT(*) 
FROM Matches 
WHERE SeasonID = @SeasonID AND 
    (HomeTeamId = X AND HomeTeamScore > VisitingTeamScore) OR 
    (VisitingTeamId = X AND VisitingTeamScore > HomeTeamScore)

-- Loses
SELECT COUNT(*) 
FROM Matches 
WHERE SeasonID = @SeasonID AND 
    (HomeTeamId = X AND HomeTeamScore < VisitingTeamScore) OR 
    (VisitingTeamId = X AND VisitingTeamScore < HomeTeamScore)

-- Ties
SELECT COUNT(*) 
FROM Matches 
WHERE SeasonID = @SeasonID AND 
    (HomeTeamId = X OR VisitingTeamId = X) 
    AND VisitingTeamScore = HomeTeamScore

即使你想将数据模型反规范化并为每个团队存储此信息,也不希望在`Teams`表中执行此操作,因为你可能需要知道给定赛季内一个团队有多少胜/负/平局(我假设一个团队可能会在多个赛季中保持不变。如果情况不是这样,请忽略此处内容)。

这是这个问题中比较容易的部分。当你决定“不创建传统的多对多关系”时,你抛弃了有趣/困难的部分。你还绕过了Rails/Arel内置的许多非常智能的功能,通过一点点思考如何以有意义的方式表示这些数据,可能会发挥这些功能。 - coreyward
@coreyward:目标是提出一个有趣且具有挑战性的解决方案吗? - Scott Mitchell
不,这是为了在可能的情况下在Ruby on Rails框架的约束条件下以清晰、有意义的方式协助建模数据。你错过了机会,使用直接的SQL解决方案抛弃了ActiveRecord,并且充斥着讨厌的驼峰式列和变量。 - coreyward
@coreyward:啊,我错过了整个Ruby on Rails部分。我在问题一开始就读到了它,但在构思我的解决方案时可能已经忽略它了。 - Scott Mitchell

0

我这里是即兴发挥,但请考虑:

tblTeam
    TeamID
    TeamName
     . . . OtherTeamFields

tblMatch
    MatchID
    MatchDate
    MatchLocationID
     . . . OtherMatchFields

tblTeam_Matches
    TeamID FK on tblTeam.TeamID
    MatchID FK on tblMatchID
    TeamStanding (Win, Loss, Tie)

以上结构有一些优缺点。从正面看,每个参与比赛的团队的结果都正确地存储了团队与该比赛之间的关系。可以通过设置TeamID和TeamStanding(即“WHERE TeamStanding =“Win””)的条件来检索每个团队的结果范围内的比赛结果。

然而,还有一种更复杂但可能更可扩展和有用的方式,那就是为tblTeam_Matches定义一个TeamScore字段。在这种情况下,比赛胜利者将由一系列相当困难的子查询确定(我说困难是指对于我而言困难,我打赌这里的人们可以快速处理样例……但它有点让人费解)。

我认为第二种选择应该是更“合适”的方法,但我尝试了一些版本的拉取:

StatsQuery:
    TeamName
    TotalMatches
    Wins
    Losses
    Ties

我遇到了一些困难。相关子查询并不是我的强项(至少目前还不是)。

无论如何,希望这能给你一些启示……


将实际分数存储起来可能比存储排名/结果更有意义。尽管如此,在这里表格之间的关系并没有很好地定义,特别是在Rails应用程序的上下文中(在其中无法在联接表中存储其他数据)。 - coreyward
啊。我不知道在Rails应用程序中关于连接表的事情。是的,分数是我处理它的首选方式,但正如我所说,当尝试在聚合记录集中找到确定每个团队胜利/失败的“优雅”方法时,查询变得非常复杂。我知道它是可以做到的,但我的大脑此刻已经炸了。 - XIVSolutions
我认为获取胜利/失败数据并不成问题,尤其是使用直接的SQL查询语句,无论它的结构如何。这就是为什么我在我的回答中更加关注如何表示关系。一旦你确定了关系,数据结构就很明显了,你可以编写SQL(或AREL语句)来生成所需的报告。 - coreyward

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接