Aktualizace:
Tyto články na mém blogu popisují rozdíly mezi metodami podrobněji:
NOT IN
vs.NOT EXISTS
vs.LEFT JOIN / IS NULL
:SQL Server
NOT IN
vs.NOT EXISTS
vs.LEFT JOIN / IS NULL
:PostgreSQL
NOT IN
vs.NOT EXISTS
vs.LEFT JOIN / IS NULL
:Oracle
NOT IN
vs.NOT EXISTS
vs.LEFT JOIN / IS NULL
:MySQL
Existují tři způsoby, jak provést takový dotaz:
-
LEFT JOIN / IS NULL
:SELECT * FROM common LEFT JOIN table1 t1 ON t1.common_id = common.common_id WHERE t1.common_id IS NULL
-
NOT EXISTS
:SELECT * FROM common WHERE NOT EXISTS ( SELECT NULL FROM table1 t1 WHERE t1.common_id = common.common_id )
-
NOT IN
:SELECT * FROM common WHERE common_id NOT IN ( SELECT common_id FROM table1 t1 )
Když table1.common_id
nemá hodnotu null, všechny tyto dotazy jsou sémanticky stejné.
Pokud je povolena hodnota null, NOT IN
je jiný, protože IN
(a proto NOT IN
) vrátí NULL
když hodnota neodpovídá ničemu v seznamu obsahujícím NULL
.
To může být matoucí, ale může to být jasnější, když si vzpomeneme na alternativní syntaxi:
common_id = ANY
(
SELECT common_id
FROM table1 t1
)
Výsledkem této podmínky je booleovský součin všech srovnání v seznamu. Samozřejmě, jeden NULL
hodnota dává NULL
výsledek, který vykreslí celý výsledek NULL
taky.
Nikdy nemůžeme s jistotou říci, že common_id
se nerovná ničemu z tohoto seznamu, protože alespoň jedna z hodnot je NULL
.
Předpokládejme, že máme tato data:
common
--
1
3
table1
--
NULL
1
2
LEFT JOIN / IS NULL
a NOT EXISTS
vrátí 3
, NOT IN
nevrátí nic (protože to bude vždy vyhodnoceno buď jako FALSE
nebo NULL
).
V MySQL
, v případě sloupce bez možnosti null LEFT JOIN / IS NULL
a NOT IN
jsou o něco málo (o několik procent) efektivnější než NOT EXISTS
. Pokud má sloupec hodnotu null, NOT EXISTS
je nejúčinnější (opět nic moc).
V Oracle
, všechny tři dotazy poskytují stejné plány (ANTI JOIN
).
V SQL Server
, NOT IN
/ NOT EXISTS
jsou efektivnější, protože LEFT JOIN / IS NULL
nelze optimalizovat na ANTI JOIN
jeho optimalizátorem.
V PostgreSQL
, LEFT JOIN / IS NULL
a NOT EXISTS
jsou efektivnější než NOT IN
, protože jsou optimalizovány na Anti Join
, zatímco NOT IN
používá hashed subplan
(nebo dokonce obyčejný subplan
pokud je poddotaz příliš velký na hašování)