NBA比赛数据库

Database for NBA games

问题

我想知道如何为 NBA 比赛设计关系数据库

Whosebug 中有几个类似的问题,但没有人给出满意的答案。

Star Schema database for NBA/Basketball statistics

Database for Basketball teams/games/scores per season

Database Design NBA

显然,篮球迷对比赛数据很感兴趣,大量网站都提供这些统计数据。
此外,篮球、足球等视频游戏也应该保持类似的数据。

有standard/recommended设计这些数据库的方法吗?

例子

我想到的解决方案如下:

团队和游戏

国家国家代码 pk,国家名称)

城市国家 pk fk,城市代码 pk,城市名称)

团队团队代码 pk,团队名称,城市fk)

姓名 pk,生日 pk,身高,体重,家乡fkCity)

Employment (Employee pk fkPerson, JoiningDate pk, TeamCode fk2, DepartureDate, Salary , 球衣号码)

游戏 (城市 pk fk1, 日期 pk, HostTeam fk2, VisitingTeam fk3)

GamePlayer (Game pk fk, Player pk fkEmployee, Position)

游戏活动

射击 (游戏 pk fk1, TimeOfGame pk, Player fk2, ShootingType, Missed )

反弹 (比赛 pk fk1, TimeOfGame pk, Player fk2, IsOffensive)

Block (Game pk fk1, TimeOfGame pk, Blocker fk2, Blocked fk3)

Steal (Game pk fk1, TimeOfGame pk, Stealer fk2, Stealed fk3)

其他游戏活动...

另一种方法是只存储每场比赛的统计数据(派生数据)。

GameStats (Game pk fk1, Player pk fk2, Minutes, FieldGoal, FieldGoalMissed , ThreePointMade, ThreePointMissed, FreeThrow, FreeThrowMissed, DefensiveRebounds, OffensiveRebounds, Blocks, ...)

历史数据

这个数据模型我遇到的一个难点是球员可以更换球队,更换球衣号码所以我们需要存储历史数据。

比赛中的事件(投篮、篮板、暂停、换人……)也是历史数据。

派生数据

我遇到的另一个困难是决定是否存储派生数据。

由于派生数据导致更新异常,我们应该避免它们。但是,我发现很难完全避免派生数据。

例如

  1. 游戏统计数据是衍生数据。为了避免它们,我们必须存储事件。
  2. 一名球员在一场比赛中的出场时间是从赛事中得出的 (Substitution/Timeout/...)。
  3. 一些统计数据是相关的,营业额来自 Steal/Block/...
  4. 对于游戏事件,游戏时间可以从一天中的时间和其他事件中推导出来 (Substitution/Timeout/...)。

为了简单起见,我们是否应该做出妥协并存储派生数据?
真正规范化的数据库是否包含派生数据?


编辑 1 - 中立球场

为了考虑到没有球队是主队的中立球场,我们可以使用以下设计。

体育场城市 pk,名称 pk,容量)

游戏 (体育场 pk fk, 日期 pk)

TeamRole (TeamRole pk) ['Home', 'Away', 'Neutral']

GameTeam (Game pk fk, Team pk fk, 团队角色 pk fk)

在不了解所有细节的情况下不可能给出完整的答案,但我可以给你一些建议,让你的生活更轻松。

在你的描述中,tables Country, City and Team 似乎不错,但我不明白为什么你需要在 Person 的 table 中输入 City fk(除非它是出生城市,但是列名应该清楚)。

就业

现在,关于就业table - 我的建议有点不同:
首先,您需要决定是否只保留球员或所有与比赛相关的球队成员(例如球队教练) table.
我会建议第二个选项,这意味着你需要为工作类型(即球员、教练、助理教练等)保留另一个 table,并在工作中对它有一个 fk table。

历史数据

至于历史数据问题 - 有一些规则你要考虑:例如,如果你的球员目前在一个球队工作,他可能不能同时在另一个球队工作,但是,他可以在受雇于常规球队的同时成为他所在国家/地区国家队的一员。为了解决这个问题,您将不得不以检查约束的形式创建一些业务逻辑规则,也许还需要创建一些触发器来保持数据完整性。
应对球队的变化非常容易,因为你有球员的加入日期和离开球队的日期 - 你所需要的只是确保常规球队中任何球员的就业之间没有重叠(记住国家队是一个例外)。

球员在球队受雇时发生变化

为了应对球衣号码的变化,或者球员在球队雇佣期间可能发生的任何数据变化,我建议在雇佣细节上添加一个table,这将与雇佣相关联table,有开始日期和结束日期,并保留球员在球队工作期间可能发生变化的所有数据。同样,您需要确保每个就业 ID 的记录不重叠(日期方面)。

活跃玩家

活跃玩家数 table 应该按游戏计算,所以游戏 ID 应该是 fk。我建议简单地使用 table 和 gameId、teamId 和 playerId,而主键是 gameId+PlayerId(我已将 teamId 排除在主键之外,因为它是另一层保护,以防就业数据混乱并且一名球员在比赛当天被视为在两支球队都受雇)

游戏

比赛table应该有比赛日期+主队+客队的主键。 请注意,比赛可能在中立的体育场举行,因此您需要在将新比赛数据插入 table 之前测试主队和客队翻转的比赛。此外,您可能希望保留一个体育场 table,它可以连接到城市,并在比赛中保留体育场 ID table 而不是城市 ID。

游戏统计

你应该努力保持一个单一的 table 来描述游戏中的所有事件。 这个 table 当然应该对比赛 table 和球队 table 有一个 fk。从你的问题我了解到统计是在玩家级别完成的,所以你也想对玩家保持一个 fk table.
添加一个 table 用于统计详细信息描述,并在游戏统计 table 中为 table 添加一个 fk。基本上,它应该是这样的:

统计详细信息 (Detail_Id, Detail_Name)
并且应该保存 shootpassrebound 等数据

在您的游戏统计信息中 table 您可能需要记录涉及多个玩家的事件。有几种方法可以做到这一点,我建议尽可能简单:将 PlayerID1、PlayerId2、PlayerId3 保留在 table 中,并让它们都可以为 null,除了第一个。