2015-10-27 3 views
2

Я столкнулся с этим журналом: http://users.dcc.uchile.cl/~cgutierr/cursos/BD/divisionSQL.pdf, который дал метод перевода деления реляционной алгебры на sql. Я немного скептически, если это на самом деле работает,Перевод реляционной алгебры деления

Учитывая T1 (A,B) and T2(B)

SELECT A FROM T1 
WHERE B IN (SELECT B FROM T2) 
GROUP BY A 
HAVING COUNT(*) = (SELECT COUNT (*) FROM T2); 

потому предположим, что вы получили строку T1 [A, B], что там было дубликатами, что удовлетворила заявление

where B in (select B from T2), не будет ли причиной having clause пропустить эту строку? или оператор «in» удаляет дубликаты?

+0

Они просто предполагают, что данные уникальны :-) Если 'B' не является уникальным, просто измените' COUNT (*) 'на' COUNT (DISTINCT B) ' – dnoeth

+0

", учитывая строку в T1 [A, B], такую, что были дубликаты, которые удовлетворяли заявлению «неясно. Несколько строк в таблице, которая соответствует той строке из какой таблицы? Пожалуйста, используйте больше слов и говорите, что вы имеете в виду. – philipxy

ответ

1

No. Реляционная алгебра с делением принимает набор отношений (A,B), и возвращает набор A таким образом, что существует связь между A и всеми членами данного подмножества B с. Например, в связанной вами бумаге a1 и a3 являются единственными A s, которые имеют отношение к b2 и b3. Строка WHERE B IN (SELECT B FROM T2) фильтрует строки T1, так что только строки с b2 или b3 находятся в столбце B. Это эквивалентно INNER JOIN между T1 и T2 на их соответствующих B с.

Обратите внимание, что в T1 или T2 нет двухместных записей. Несколько эквивалентных запросов (плюс эквивалент в журнале, хотя отмечают их предостережение, что эти запросы возвращают пустое множество, если T2 пуст, в отличие от Q1 газеты):

SELECT A FROM T1 
WHERE EXISTS(SELECT 1 FROM T2 WHERE T2.B = T1.B) 
GROUP BY A 
HAVING COUNT(*) = (SELECT COUNT (*) FROM T2); 

SELECT A FROM T1 
INNER JOIN T2 ON T1.B = T2.B 
GROUP BY A 
HAVING COUNT(*) = (SELECT COUNT (*) FROM T2); 
0

Ваш вопрос остается неясным. Но вы, похоже, задаете следующий запрос Q0: Когда строка T1 соответствует нескольким/повторяющимся строкам T2, будет использовать фильтр равенства COUNT, это результат и поэтому не даст правильного ответа?

Если дубликатов строки в T1 [sic] нет, тогда да, это будет отфильтровано. (В противном случае это может быть или не быть.) Но нет повторяющихся строк в реляционной алгебре, так что это все спорно.

Для обработки дубликатов данных в SQL вы должны решить, что вы хотите «разделить на», чтобы иметь в виду, когда есть повторяющиеся строки. Вы можете повторно использовать определение алгебры, в то время как имена других операторов алгебр должны быть аналогично названы операторами SQL/bag, но вы получаете разные результаты в зависимости от того, с каким определением вы начинаете.

В любом случае Q0 не возвращает деление. Отдел может возвращать строки T1, B не отображается в T2; Q0 не может. Отдел возвращает строки AB из T1, где A появляется в T1 с каждой строкой T2 и некоторой строкой T2. Q0 возвращает строки AB из T1, где A появляется в T1 с каждой строкой T2 и только с строками из T2.

Фактически реляционное деление Q0 и Q1 запрашивают три разных набора строк. Q1 возвращает строки AB из T1, где A появляется в T1 с каждой строкой T2.

Бумага плохо написана:

  • Q0 не рассчитывает реляционное деление.

  • Бумага называет запрос Q1 «классической версией» деления, но Q1 не является делением. (В работе подтверждает это с помощью «код для Q0 и Q1 производить два разных результатов» пока противоречит себе, вызывая Q1 «выполнение оператора деления» и Q0 «альтернативной реализации».)

PS: SELECT удаляет дубликаты тогда и только тогда, когда указан DISTINCT. IN указывает, находится ли строка в таблице. Вопрос о том, является ли строка В версии DISTINCT, всегда совпадает с вопросом о том, находится ли она в версии, отличной от DISTINCT. Предполагая, что мы хотим, чтобы строки WHERE были введены в подзапрос, нет необходимости использовать DISTINCT.

Смежные вопросы