Tylko uważaj na różnicę z połączeniami zewnętrznymi. Zapytanie, w którym filtr b.IsApproved
(w prawej tabeli, Bar) jest dodany do ON
warunek JOIN
:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId);
Jest NIE tak samo jak umieszczenie filtra w WHERE
klauzula:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved = 1);
Ponieważ dla 'failed' zewnętrznych łączy do Bar
(tzn. tam, gdzie nie ma b.BarId
dla f.BarId
), spowoduje to pozostawienie b.IsApproved
jako NULL
dla wszystkich takich nieudanych wierszy sprzężenia, a następnie zostaną one odfiltrowane.
Innym sposobem patrzenia na to jest to, że dla pierwszego zapytania LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId)
zawsze zwróci LEFT wiersze tabeli, ponieważ LEFT OUTER JOIN
gwarantuje, że LEFT wiersze tabeli zostaną zwrócone, nawet jeśli łączenie się nie powiedzie. Jednak efekt dodania (b.IsApproved = 1)
do LEFT OUTER JOIN
warunkiem jest NULL wszystkich prawych kolumn tabeli, gdy (b.IsApproved = 1)
jest fałszywe, tj. zgodnie z tymi samymi zasadami, które zwykle stosuje się do LEFT JOIN
warunek na (b.BarId = f.BarId)
.
Aktualizacja :Aby uzupełnić pytanie zadane przez Conrada, odpowiednikiem LOJ dla filtra OPCJONALNEGO byłoby:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved IS NULL OR b.IsApproved = 1);
czyli WHERE
Klauzula musi uwzględniać oba warunki, czy łączenie się nie powiedzie (NULL)
a filtr ma zostać zignorowany, a gdzie łączenie się powiedzie, a filtr musi zostać zastosowany. (b.IsApproved
lub b.BarId
można przetestować pod kątem NULL
)
Umieściłem tutaj SqlFiddle, który pokazuje różnice między różnymi miejscami b.IsApproved
filtr względem JOIN
.