Как представить реляционное деление (выражение базовой алгебры) с точки зрения SQL

Query: Найдите имена моряков, забронировавших все лодки

Это можно представить в алгебре отношений следующим образом:
1. πsname ( ((σsid,bid Reserves) / (σbid Boats)) ⋈ Sailors)

Согласно реляционной алгебре, деление также может быть представлено с помощью оператора базовой алгебры следующим образом:

  1. A/B= πx(A) - πx((πx(A) * B) - A )

Таким образом, если я convert заявление 1 в соответствии с заявлением 2 тогда

  1. Reserves/Boats= πsid(Reserves) - πsid(( πbid(Reserves) * Boats) - Reserves )

Как я могу представить Statement 3 в терминах SQL так же, как в алгебре отношений (т.е. без использования какого-либо оператора, кроме minus/Except(-) and Cross join(*)).
Я пытаюсь добиться этого без использования условия NOT EXISTS and EXISTS.

Схема таблиц следующая:
Sailors(sid: целое, sname: строка, rating: целое, age: real)
Boats(bid: целое, bname: строка, color: строка)
Reserves( sid: целое число, ставка: целое число, день: дата)


person Ankita Rane    schedule 30.09.2015    source источник
comment
Было бы полезно, если бы вы встроили SQLFiddle, заполненный данными, которые вы хотели бы использовать , и если бы вы представили себе ожидаемые результаты. Узнайте, как задать хороший вопрос. Спасибо.   -  person Bob Jarvis - Reinstate Monica    schedule 30.09.2015
comment
простой -talk.com/sql/t-sql-programming/   -  person shawnt00    schedule 30.09.2015


Ответы (2)


Учитывая этот DDL для таблиц, соответствующих вашим соответствующим отношениям:

create table Boats(
  bid int,
  bname varchar(50),
  color varchar(50)
);

create table Reserves(
  sid int,
  bid int,
  day date
);

Вы можете довольно просто транслитерировать формулу деления (3) в синтаксис Oracle SQL, хотя это и многословно:

-- All sailors who reserved at least one boat
SELECT DISTINCT sid
FROM Reserves

MINUS 

-- All sailors who reserved at least one boat, but not all of them
SELECT sid
FROM (
  -- all combinations of a sailor who reserved any boat with any boat
  -- available to be reserved:
  SELECT Reserves.sid, Boats.bid
  FROM
    Reserves
    CROSS JOIN
    Boats

  MINUS

  -- all combinations of sailor and boat for actual reservations made
  SELECT sid, bid
  FROM Reserves
) sids

Как указано, в нем используются только операции CROSS JOIN и MINUS, чтобы напрямую соответствовать формуле реляционной алгебры. Однако в реальном приложении базы данных можно было бы наверняка получить тот же результат с помощью совершенно другого запроса.

Обратите также внимание на то, что базы данных SQL могут нарушать и нарушают принцип формальной реляционной алгебры, согласно которому отношения не содержат повторяющихся кортежей. Это причина SELECT DISTINCT в первом подзапросе. Отдельный выбор, применяемый стратегически в другом месте запроса, может сделать его более эффективным, но не изменит результат.

person John Bollinger    schedule 30.09.2015

Запрос будет таким:

select 
  sailors.sname 
from (
  select r.sid 
    from reserves r 
   group by r.sid
   having count(distinct r.bid) = (select count(*) from boats) ) fullRes
join sailors 
on sailors.sid = fullRes.sid

Вы можете протестировать его здесь:

Пример

person dcieslak    schedule 30.09.2015