Uppdatering:
Dessa artiklar i min blogg beskriver skillnaderna mellan metoderna mer i detalj:
NOT INkontraNOT EXISTSkontraLEFT JOIN / IS NULL:SQL ServerNOT INkontraNOT EXISTSkontraLEFT JOIN / IS NULL:PostgreSQLNOT INkontraNOT EXISTSkontraLEFT JOIN / IS NULL:OracleNOT INkontraNOT EXISTSkontraLEFT 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)