Uppdatering:
Dessa artiklar i min blogg beskriver skillnaderna mellan metoderna mer i detalj:
NOT IN
kontraNOT EXISTS
kontraLEFT JOIN / IS NULL
:SQL Server
NOT IN
kontraNOT EXISTS
kontraLEFT JOIN / IS NULL
:PostgreSQL
NOT IN
kontraNOT EXISTS
kontraLEFT JOIN / IS NULL
:Oracle
NOT IN
kontraNOT EXISTS
kontraLEFT JOIN / IS NULL
:MySQL
Det finns tre sätt att göra en sådan fråga:
-
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 )
När table1.common_id
är inte nullbar, alla dessa frågor är semantiskt desamma.
När den är nullbar, NOT IN
är annorlunda eftersom IN
(och därför NOT IN
) returnera NULL
när ett värde inte matchar något i en lista som innehåller en NULL
.
Detta kan vara förvirrande men kan bli mer uppenbart om vi minns den alternativa syntaxen för detta:
common_id = ANY
(
SELECT common_id
FROM table1 t1
)
Resultatet av detta tillstånd är en boolesk produkt av alla jämförelser i listan. Naturligtvis en enda NULL
värde ger NULL
resultat som återger hela resultatet NULL
också.
Vi kan aldrig säga definitivt att common_id
är inte lika med någonting från den här listan, eftersom minst ett av värdena är NULL
.
Anta att vi har dessa data:
common
--
1
3
table1
--
NULL
1
2
LEFT JOIN / IS NULL
och NOT EXISTS
returnerar 3
, NOT IN
kommer att returnera inget (eftersom det alltid kommer att utvärderas till antingen FALSE
eller NULL
).
I MySQL
, i fallet på icke-nullbar kolumn, LEFT JOIN / IS NULL
och NOT IN
är lite (flera procent) mer effektiva än NOT EXISTS
. Om kolumnen är nullbar, NOT EXISTS
är den mest effektiva (igen, inte mycket).
I Oracle
, ger alla tre frågorna samma planer (en ANTI JOIN
).
I SQL Server
, NOT IN
/ NOT EXISTS
är mer effektiva eftersom LEFT JOIN / IS NULL
kan inte optimeras till en ANTI JOIN
av dess optimerare.
I PostgreSQL
, LEFT JOIN / IS NULL
och NOT EXISTS
är mer effektiva än NOT IN
, utan att de är optimerade till en Anti Join
, medan NOT IN
använder hashed subplan
(eller till och med en vanlig subplan
om underfrågan är för stor för att hasha)