sql >> Databáze >  >> RDS >> Sqlserver

Ustanovení WHERE vs ON při použití JOIN

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 .



  1. Jak vybrat a seřadit podle sloupců, které nejsou v SQL příkazu Groupy By - Oracle

  2. Jak Cosd() funguje v PostgreSQL

  3. Jak číslovat řádky v SQL

  4. Know-How k obnovení smazaných záznamů v SQL Server