Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database design 数据库设计建议(具体示例-幻想足球)_Database Design - Fatal编程技术网

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团队从他们的签约球员中选择那些将在该轮为他们效力的球员。这是由圆形玩家代表的
问题在于,轮回球员和统计数据之间存在一定程度的尴尬。从逻辑上讲,一个回合玩家有一行统计数据来代表他们在该回合中的表现(如果他们参加了比赛)。这是一对一的关系,但两个表都是可选的。一名球员可能不会在一轮比赛中出场,因此没有统计数据。玩家也可能不会被选为RoundPlayer,因此该表中没有行。一个由圆形和PlayerId键控,另一个由圆形和收缩键控。从一个导航到另一个有点尴尬,特别是当尝试使用ORM(例如Entity Framework 4)时,因为导航属性基于外键,而这种关系通过中间表(契约)获得PlayerId

我曾经考虑过在统计数据中添加收缩(如果一名球员被选中参加那轮比赛),但那感觉是错误的。我还考虑过删除Stat和Roundplayer之间的1:1关系,并将它们移动到一张桌子上,但这感觉也是错误的

我很感激任何关于如何在RoundPlayer和Stat之间建立更好关系的想法,甚至任何可能完全改变这种结构的想法


在我看来,我认为你也看到了同样的缺陷,那就是你有两个表,它们的记录彼此直接相关,但它们有完全不同的键

正如我理解你的描述,如果有一个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