Database design 数据库设计建议(具体示例-幻想足球)
我有一个幻想足球比赛的数据库。 有三种模式:Database design 数据库设计建议(具体示例-幻想足球),database-design,Database Design,我有一个幻想足球比赛的数据库。 有三种模式: afl(与澳大利亚足球联盟实体相关) ddhp(与当地幻想竞赛实体相关)和 dbo(适用于任何一方未具体拥有的实体) 实体说明 每个球员都为一个AFL球队踢球(不需要按时间跟踪,所以我只记录球员所效力的当前球队,如果球员更换俱乐部,则更新此记录) 有些球员为ddhp球队踢球。这是由一个包含FromRound和ToRound的合同表示的,表示合同有效的时间边界 有子弹。afl和ddhp之间基本上没有区别,所以只有一张桌子 有一些赛程,代表两支dd
- afl(与澳大利亚足球联盟实体相关)
- ddhp(与当地幻想竞赛实体相关)和
- dbo(适用于任何一方未具体拥有的实体)
- 每个球员都为一个AFL球队踢球(不需要按时间跟踪,所以我只记录球员所效力的当前球队,如果球员更换俱乐部,则更新此记录)
- 有些球员为ddhp球队踢球。这是由一个包含FromRound和ToRound的合同表示的,表示合同有效的时间边界
- 有子弹。afl和ddhp之间基本上没有区别,所以只有一张桌子
- 有一些赛程,代表两支ddhp球队在一轮比赛中相互对抗
- 当一名球员在一轮比赛中出场时,他们会记录统计数据
- 每一轮,每个ddhp团队从他们的签约球员中选择那些将在该轮为他们效力的球员。这是由圆形玩家代表的
在我看来,我认为你也看到了同样的缺陷,那就是你有两个表,它们的记录彼此直接相关,但它们有完全不同的键 正如我理解你的描述,如果有一个RoundPlayers记录,那么总是有一个匹配的统计数据记录,反之亦然。在这种情况下,我认为教科书上的答案是: (a) 将两者合并成一个记录。他们总是在一起,为什么不为他们创造一张唱片呢?我认为不这样做的主要原因是,也许一个回合玩家在不同的环境中比一个统计数据有趣。也就是说,当我们安排时间时,一个轮型球员是有趣的,但是一个统计数据对于球员表现的长期积累是有趣的 或者(b)将统计数据中的外键扔掉给团队、球员和回合。相反,为RoundPlayer提供一个外键,或者复制到Contract和Round的链接。这会使你的钥匙保持一致 对我来说,与团队的联系似乎特别可疑。你不能通过球员找到球队吗?如果玩家切换到另一个球队,那么统计数据中的球队是否应该更新以匹配?如果是这样的话,这是多余的,并且会造成两者不同步的可能性。或者统计数据是否与原始团队保持一致?但是,由于这是一个AFL团队,而不是一个DDHP团队,团队到底有什么区别呢?也许我误解了一个要求。我对澳大利亚足球一无所知。(这一定是一场非常困难的比赛,因为所有球员都必须倒挂在地上进行比赛……)问题 由于基于
记录ID
的数据模型,您遇到的主要问题是导航
[d] 问题在于,轮回玩家和统计数据之间存在一定程度的尴尬。[e] 一个由圆形和PlayerId键控,另一个由圆形和收缩键控。从一个导航到另一个有点尴尬 这条线很旧,但没有答案,你说: 我很感激任何关于如何在RoundPlayer和Stat之间建立更好关系的想法,甚至任何可能完全改变这种结构的想法 您遇到的问题远不止这一个:您的大多数查询代码都将是可怕的。这些困难[d][e]是基于
记录ID
的模型导致的典型问题。你已经知道你的导航和查询代码很难,所以我不会告诉你任何你不知道的事情。您已经实现了一个常见的模型,它来自于大量宣传和营销为“关系型”的教科书和帖子,但实际上并不正确
关系模型
E F Codd博士的关系模型专门设计用于防止所有此类问题,并使查询更直接。它有逻辑的基础(“数学”是逻辑的表达),一阶谓词演算(又名一阶逻辑),因此它有一个科学稳健的基础。
只有理解并应用整个RM(而不是片段),才能实现RM的好处
权威源文件仅为:
- Codd的1970年
- Codd的1985年
- 请注意,Codd不是“关系模型的先驱”,他是唯一的发明家。这种观点试图将批评者定位为“其他先驱”。这不是一列马车,而是一个孤独的流浪者
- 请注意,没有任何学术论文是为了阐明、扩展或推进
SELECT Year, Team.Team, -- ShortName Coach = LastName + "," + FirstName, SUM( Value ) FROM Team JOIN PlayerStats ON Team.Team = PlayerStats.Team JOIN Person ON Team.CoachId = Person.PersonId, ( SELECT DISTINCT Year FROM Round ) Year WHERE Metric = "Goal" AND SUM( Value ) NOT NULL GROUP BY Year, Team, Coach
SELECT TeamAFL.TeamAFL, -- ShortName Player = LastName + "," + FirstName, SUM( Value ) FROM TeamAFL JOIN Player ON TeamAFL.TeamAFL = Player.TeamAFL JOIN PlayerStats ON Player.PlayerId = PlayerStats.PlayerId JOIN Person ON Player.PlayerId = Person.PersonId WHERE Year = "2017" AND Metric = "Goal" GROUP BY Team, Player