Aktualizace:
Tyto články na mém blogu popisují rozdíly mezi metodami podrobněji:
NOT INvs.NOT EXISTSvs.LEFT JOIN / IS NULL:SQL ServerNOT INvs.NOT EXISTSvs.LEFT JOIN / IS NULL:PostgreSQLNOT INvs.NOT EXISTSvs.LEFT JOIN / IS NULL:OracleNOT INvs.NOT EXISTSvs.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í)