Я получаю разные результаты в зависимости от условия фильтра в запросе, в зависимости от того, где я размещаю условие фильтра. Мои вопросы:
- Есть ли техническая разница
между этими запросами?
- Есть ли что-нибудь в стандарте SQL
это объясняет разные
наборы записей из запросов?
Учитывая упрощенный сценарий:
--Table: Parent Columns: ID, Name, Description
--Table: Child Columns: ID, ParentID, Name, Description
--Query 1
SELECT p.ID, p.Name, p.Description, c.ID, c.Name, c.Description
FROM Parent p
LEFT OUTER JOIN Child c ON (p.ID = c.ParentID)
WHERE c.ID IS NULL OR c.Description = 'FilterCondition'
--Query 2
SELECT p.ID, p.Name, p.Description, c.ID, c.Name, c.Description
FROM Parent p
LEFT OUTER JOIN Child c
ON (p.ID = c.ParentID AND c.Description = 'FilterCondition')
Я предполагал, что запросы будут возвращать одинаковые наборы результатов, и я был удивлен, когда они этого не сделали. Я использую MS SQL2005, и в реальных запросах запрос 1 возвратил ~ 700 строк, а запрос 2 вернул ~ 1100 строк, и я не смог определить шаблон, по которому были возвращены строки, а какие были исключены. В запросе 1 было еще много строк с дочерними строками с данными и данными NULL. Я предпочитаю стиль запроса 2 (и я думаю, что он более оптимален), но я думал, что запросы будут возвращать те же результаты.
Редактировать / Резюме:
Здесь были даны отличные ответы. Мне было трудно выбрать, кому присудить ответ. Я решил пойти с MDMA, так как это был первый ответ и один из самых ясных. Основываясь на предоставленных ответах, вот мое резюме:
Возможные результаты:
- A: Родитель без детей
- B: родители с детьми
- | -> B1: родители с детьми, у которых ни один ребенок не соответствует фильтр
- \ -> B2: родители с детьми, у которых 1 или более соответствуют фильтру
Результаты запроса:
- Запрос 1 возвращает (A, B2)
- Запрос 2 возвращает (A, B1, B2)
Запрос 2 всегда возвращает родителя из-за левого соединения. В запросе 1 предложение WHERE выполняется после левого соединения, поэтому исключаются родители с детьми, у которых ни один из детей не соответствует фильтру (случай B1).
Примечание: в случае B1 возвращается только родительская информация, а в случае B2 возвращается только информация о родителе / потомке, соответствующая фильтру.
HLGEM предоставил хорошую ссылку:
http://wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN