Операция деления на реляционную алгебру - PullRequest
0 голосов
/ 06 июня 2018

У меня есть эта схема:

CLUB(Name, Address, City)
TEAM(TeamName, club)
PLAYER(Badge, teamName)
MATCH(matchNumber, player1, player2, club, winner)
  • Клуб в КОМАНДА ссылки Имя в КЛУБ ;
  • teamName в PLAYER ссылки TeamName в TEAM ;
  • Player1, игрок 2, победитель в МАТЧ ссылка Знак в ИГРОК ;
  • Клуб в MATCH ссылки Имя в CLUB ;

Игрок может быть частью только одной команды.Матчи могут быть сыграны между товарищами по команде.У команды может быть только один клуб.

И мне нужно сделать это соотношение алгебры:

Извлечь игроков, которые всегда выигрывали, и связанную команду.

Я знаю, что это можно сделать с помощью структурированной операции деления:

r(A, B) / s(B)

Дело в том, что я не знаю, как ее настроить.В первом отношении у меня есть атрибут A, который я хочу извлечь (я полагаю), поэтому он должен быть «TeamName».Второй (B) должен быть одним атрибутом, который является общим с s (B) (где s (B) является подмножеством r (A, B)).В этом случае это может быть атрибут «Победитель»?

1 Ответ

0 голосов
/ 08 июня 2018

ОК, давайте соберем некоторые строительные блоки.

Примечание к записи: я использую греческие буквы для операторов отношений;угловые скобки вокруг имен атрибутов для них (обычно показаны суффиксами);круглые скобки для параметра отношения.

  • Игроки, которые сыграли и выиграли хотя бы один матч:

    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)
    
    • Быстрый:какие атрибуты в результате?Почему?
    • Тогда как мы получим «связанную команду» за исходный вопрос?
    • Это подмножество (не обязательно правильное) PlayednWonAll.Почему?

Обратите внимание, что с отношением PlayednWonAll или PlayednBeatAll в результате может быть много игроков: Анна выиграла каждый сыгранный матч;Барбара тоже.Как так?Потому что Анна никогда не играла на Барбаре;нет абсолютного чемпионаВ случае PlayednBeatAll это означает, что Анна и Барбара сыграли всех, кроме друг друга.

В чем разница между PlayednWonAll по сравнению с PlayednBeatAll?Карла сыграла только один матч против Донны, который выиграл Карла.Анна и Барабара сыграли и выиграли не только у Донны, но и у Эмилии (ни одна из них не сыграла Карлу).Таким образом, Анна и Барбара появляются в обоих результатах, Карла только в PlayednWonAll.

  • Вот бесполезный разрыв:

    ThinkAboutIt := WinnernLoser ÷ π⟨Badge⟩(PLAYER)
    
    • PLAYER возможно включает в себяигроки, которые никогда не играли.Тогда никто не мог их победить.Даже если каждый PLAYER сыграл:
    • PLAYER включает всех, кто "всегда выиграл";они не могли потерять себя.
    • IOW ThinkAboutIt всегда пусто.

Похоже, именно поэтому я считаю преподавание реляционного разрыва бессмысленным.На самом деле существует несколько вариантов деления, каждый из которых пытается по-разному справиться с угловыми случаями, такими как пустые отношения или делители с атрибутами, а не подмножеством делимого.(Или семантика типа «всегда выигрывал» против «никогда не проигрывал».) И лекторы / учебники редко разбираются в тонкостях.

Более того, в SQL нет разделения, поэтому изучение его имеет минимальную выгоду.Деление всегда может быть получено другими операторами, и обычно они дают такое же сжатое выражение и выражение, которое легче понять.(Я имею в виду другие операторы RA: в SQL для имитации деления нужен ужасный код, как обычно.) QED.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...