代码之家  ›  专栏  ›  技术社区  ›  JimBelushi2

关系代数上的除法运算

  •  -1
  • JimBelushi2  · 技术社区  · 7 年前

    我有这个模式:

    CLUB(Name, Address, City)
    TEAM(TeamName, club)
    PLAYER(Badge, teamName)
    MATCH(matchNumber, player1, player2, club, winner)
    
    • 俱乐部 在里面 团队 参考文献 名字 在里面 俱乐部 ;
    • 团队名称 在里面 玩家 参考文献 团队名称 在里面 团队 ;
    • 一号,二号,赢家 在里面 比赛 参考 徽章 在里面 玩家 ;
    • 俱乐部 在里面 比赛 参考文献 名字 在里面 俱乐部 ;

    一个球员只能是一个队的一员。比赛可以在队友之间进行。一个队只能有一个俱乐部。

    我需要做这个代数关系:

    抽取一直获胜的球员和相关团队。

    我知道这也可以通过使用division操作来实现:

    r(A, B) / s(B)
    

    事实上,我不知道如何设置它。在第一个关系中,我有一个属性a,这是我想要提取的(我猜),所以应该是“teamname”。第二个(b)应该是与s(b)相同的一个属性(其中s(b)是r(a,b)的子集)。在这种情况下,它能成为“赢家”的属性吗?

    1 回复  |  直到 7 年前
        1
  •  2
  •   AntC    7 年前

    好的,让我们组装一些积木。

    注意:我用希腊字母表示关系运算符;用尖括号括住它们的属性名(通常显示为后缀);用圆括号括住关系参数。

    • 至少赢过一场比赛的玩家:

      PlayednWon := ρ⟨Badge := winner⟩(π⟨winner⟩(MATCH))
      
    • 至少输掉一场比赛的玩家:

      PlayednLost := ρ⟨Badge := player1⟩(π⟨player1⟩(σ⟨winner ≠ player1⟩(MATCH)))
                     ∪
                     ρ⟨Badge := player2⟩(π⟨player2⟩(σ⟨winner ≠ player2⟩(MATCH)))
      
    • 每一场比赛都赢的球员。(即从未玩过和输过)

      PlayednWonAll := PlayednWon - PlayednLost
      
    • 从来没有输过的球员(可能是因为他们从来没有打过球)

      NeverLost := π⟨Badge⟩(PLAYER) - PlayednLost
      

    到目前为止不需要任何关系划分。我也看不出这会使这些更简洁。我稍后再添加一些代码。

    你是不是忠实地复制了这道试题?例如,你被告知 MATCH 包括整个联盟中每个可能的球员配对之间的至少一场比赛?关于使用除法的目的,课程告诉了你什么?

    这道考试题是否给围绕合理情景进行创造性思考的额外分数?演讲者是虐待狂吗?讲师是否理解ra,或者在开始讨论sql之前,这是对主题的某种象征性的覆盖?

    我可以猜测你为什么被告知“队友之间可以比赛”。

    • 假设这个查询是在寻找那些“总是赢”的球员。 这对除法很有用。
    • 那么报告“相关团队”就有了意义: 一个特定的球员可能“总是赢”几个不同的队; 我们想报告每一支这样的球队——不一定是球员的“主队”。
    • 但它可能包括“主队”(因为“比赛可以在队友之间进行)。 然后有一个问题:没有玩家可以玩自己(大概); 然后他们需要打比赛,并且“总是一个”对他们的“主队”里的每个人,除了他们自己。

    为了探索所有这些可能性,考试会给分数吗?

    Addit: 让我们用除法找出一个微妙的变体。

    • 另一个构造块:将 winner 每场比赛的失败者 PlayednLost ):

      WinnernLoser := ρ⟨Badge := player1⟩(π⟨winner, player1⟩(σ⟨winner ≠ player1⟩(MATCH)))
                      ∪
                      ρ⟨Badge := player2⟩(π⟨winner, player2⟩(σ⟨winner ≠ player2⟩(MATCH)))
      
    • 现在那些站在胜利者一边对抗所有输掉的人:

      PlayednBeatAll := WinnernLoser ÷ PlaydnLost
      // equivalently:  WinnernLoser ÷ π⟨Badge⟩(WinnernLoser)
      
      • 快速:结果中有哪些属性?为什么?
      • 那么,我们如何让“相关团队”回答最初的问题呢?
      • 这是一个子集(不是NEC。适当) PlayednWonAll . 为什么?

    注意与关系 全方位播放 PlayednBeatAll ,结果中可能有许多球员:安娜赢得了她打的每一场比赛;芭芭拉也赢了。怎么会?因为安娜从来没有和芭芭拉比赛过,没有总冠军。在这种情况下 播放时间 ,这意味着安娜和芭芭拉除了彼此之外,谁都演过。

    有什么区别 全方位播放 播放时间 ?卡拉只打了一场比赛,对阵唐娜,卡拉赢了。安娜和巴拉巴拉不仅与唐娜,而且与埃米利娅(也没有与卡拉)比赛并取得胜利。所以安娜和芭芭拉出现在两个结果中,卡拉只出现在 全方位播放 .

    • 这里有一个无用的划分:

      ThinkAboutIt := WinnernLoser ÷ π⟨Badge⟩(PLAYER)
      
      • PLAYER 可能包括从未玩过的玩家。 那就没人能打败他们了。即使每 玩家 发挥:
      • 玩家 包括所有“总是赢”的人; 他们不可能迷失自我。
      • 低潮 ThinkAboutIt 总是空的。

    明白了,这就是为什么我认为教关系分界是没有意义的。实际上,除法有几个变体,每个变体都试图以不同的方式处理角点情况,例如空关系或属性不是被除数子集的除数。(或者像“总是赢”和“从不输”这样的语义学)而讲师/教科书很少涉及微妙之处。

    此外,在sql中不提供divide,因此了解它的好处微乎其微。除法通常可以由其他运算符获得,并且这些运算符通常给出一个同样简洁的表达式,以及一个更易于理解的表达式。(我是说其他ra操作符:在sql模拟中,divide和往常一样需要可怕的代码。)qed。