Jen pozor na rozdíl s vnějšími spoji. Dotaz, kde je filtr b.IsApproved
(v pravé tabulce, Bar) je přidán do ON
stav JOIN
:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId);
NENÍ stejně jako umístění filtru do WHERE
klauzule:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved = 1);
Od pro 'failed' vnější spojení s Bar
(tj. tam, kde není b.BarId
pro f.BarId
), tím zůstane b.IsApproved
jako NULL
pro všechny takto neúspěšné řádky spojení a tyto řádky budou poté odfiltrovány.
Jiný způsob, jak se na to podívat, je, že pro první dotaz LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId)
vždy vrátí LEVÉ řádky tabulky, protože LEFT OUTER JOIN
zaručuje, že LEVÉ řádky tabulky budou vráceny, i když se spojení nezdaří. Efekt přidání (b.IsApproved = 1)
do LEFT OUTER JOIN
podmínkou je vynulovat všechny pravé sloupce tabulky, když (b.IsApproved = 1)
je false, tj. podle stejných pravidel, která se běžně používají pro LEFT JOIN
podmínka na (b.BarId = f.BarId)
.
Aktualizovat :K dokončení otázky, kterou položil Conrad, ekvivalentní LOJ pro VOLITELNÝ filtr by byl:
SELECT *
FROM Foo f
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE (b.IsApproved IS NULL OR b.IsApproved = 1);
tj. WHERE
klauzule musí vzít v úvahu jak podmínku, zda spojení selže (NULL)
a filtr má být ignorován a tam, kde je spojení úspěšné, musí být použit filtr. (b.IsApproved
nebo b.BarId
lze testovat na NULL
)
Zde jsem sestavil soubor SqlFiddle, který ukazuje rozdíly mezi různými umístěními b.IsApproved
filtr vzhledem k JOIN
.