Aktualisierung:
Diese Artikel in meinem Blog beschreiben die Unterschiede zwischen den Methoden genauer:
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
Es gibt drei Möglichkeiten, eine solche Abfrage durchzuführen:
-
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 )
Wenn table1.common_id
nicht nullable ist, sind alle diese Abfragen semantisch gleich.
Wenn es nullfähig ist, NOT IN
ist anders, da IN
(und daher NOT IN
) gibt NULL
zurück wenn ein Wert mit nichts in einer Liste übereinstimmt, die einen NULL
enthält .
Das mag verwirrend sein, wird aber offensichtlicher, wenn wir uns an die alternative Syntax dafür erinnern:
common_id = ANY
(
SELECT common_id
FROM table1 t1
)
Das Ergebnis dieser Bedingung ist ein boolsches Produkt aller Vergleiche innerhalb der Liste. Natürlich ein einzelnes NULL
value ergibt den NULL
Ergebnis, das das gesamte Ergebnis NULL
darstellt auch.
Wir können niemals definitiv sagen, dass common_id
ist mit nichts aus dieser Liste gleich, da mindestens einer der Werte NULL
ist .
Angenommen, wir haben diese Daten:
common
--
1
3
table1
--
NULL
1
2
LEFT JOIN / IS NULL
und NOT EXISTS
gibt 3
zurück , NOT IN
gibt nichts zurück (da es immer entweder zu FALSE
ausgewertet wird oder NULL
).
In MySQL
, falls es sich um eine nicht nullfähige Spalte handelt, LEFT JOIN / IS NULL
und NOT IN
sind etwas (mehrere Prozent) effizienter als NOT EXISTS
. Wenn die Spalte nullfähig ist, NOT EXISTS
ist am effizientesten (wiederum nicht viel).
In Oracle
, ergeben alle drei Abfragen dieselben Pläne (ein ANTI JOIN
).
In SQL Server
, NOT IN
/ NOT EXISTS
sind effizienter, da LEFT JOIN / IS NULL
kann nicht auf einen ANTI JOIN
optimiert werden durch seinen Optimierer.
In PostgreSQL
, LEFT JOIN / IS NULL
und NOT EXISTS
sind effizienter als NOT IN
, da sie auf einen Anti Join
optimiert sind , während NOT IN
verwendet hashed subplan
(oder sogar ein einfacher subplan
wenn die Unterabfrage zu groß zum Hashen ist)