Opdatering:
Disse artikler i min blog beskriver forskellene mellem metoderne mere detaljeret:
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
Der er tre måder at udføre sådan en forespørgsel på:
-
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
er ikke nullbar, er alle disse forespørgsler semantisk ens.
Når den er nullbar, NOT IN
er anderledes, da IN
(og derfor NOT IN
) returner NULL
når en værdi ikke matcher noget på en liste, der indeholder en NULL
.
Dette kan være forvirrende, men kan blive mere indlysende, hvis vi husker den alternative syntaks for dette:
common_id = ANY
(
SELECT common_id
FROM table1 t1
)
Resultatet af denne tilstand er et boolsk produkt af alle sammenligninger på listen. Selvfølgelig en enkelt NULL
værdien giver NULL
resultat, som gengiver hele resultatet NULL
også.
Vi kan aldrig sige bestemt, at common_id
er ikke lig med noget fra denne liste, da mindst én af værdierne er NULL
.
Antag, at vi har disse data:
common
--
1
3
table1
--
NULL
1
2
LEFT JOIN / IS NULL
og NOT EXISTS
returnerer 3
, NOT IN
returnerer intet (da det altid vil evaluere til enten FALSE
eller NULL
).
I MySQL
, i tilfælde af ikke-nulbar kolonne, LEFT JOIN / IS NULL
og NOT IN
er en lille smule (adskillige procent) mere effektive end NOT EXISTS
. Hvis kolonnen er nullbar, NOT EXISTS
er den mest effektive (igen, ikke meget).
I Oracle
, giver alle tre forespørgsler samme planer (en ANTI JOIN
).
I SQL Server
, NOT IN
/ NOT EXISTS
er mere effektive, da LEFT JOIN / IS NULL
kan ikke optimeres til en ANTI JOIN
af dens optimizer.
I PostgreSQL
, LEFT JOIN / IS NULL
og NOT EXISTS
er mere effektive end NOT IN
, sine er de optimeret til en Anti Join
, mens NOT IN
bruger hashed subplan
(eller endda en almindelig subplan
hvis underforespørgslen er for stor til at hash)