Aktualizacja:
Te artykuły na moim blogu bardziej szczegółowo opisują różnice między metodami:
NOT INw porównaniu zNOT EXISTSaLEFT JOIN / IS NULL:SQL ServerNOT INw porównaniu zNOT EXISTSaLEFT JOIN / IS NULL:PostgreSQLNOT INw porównaniu zNOT EXISTSaLEFT JOIN / IS NULL:OracleNOT INw porównaniu zNOT EXISTSaLEFT JOIN / IS NULL:MySQL
Takie zapytanie można wykonać na trzy sposoby:
-
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 )
Kiedy table1.common_id nie jest nullable, wszystkie te zapytania są semantycznie takie same.
Gdy jest nullable, NOT IN jest inny, ponieważ IN (i dlatego NOT IN ) zwróć NULL gdy wartość nie pasuje do niczego na liście zawierającej NULL .
Może to być mylące, ale może stać się bardziej oczywiste, jeśli przypomnimy sobie alternatywną składnię:
common_id = ANY
(
SELECT common_id
FROM table1 t1
)
Wynik tego warunku jest iloczynem logicznym wszystkich porównań na liście. Oczywiście pojedynczy NULL wartość zwraca NULL wynik, który renderuje cały wynik NULL też.
Nigdy nie możemy jednoznacznie stwierdzić, że common_id nie jest równa niczemu z tej listy, ponieważ przynajmniej jedna z wartości to NULL .
Załóżmy, że mamy te dane:
common
--
1
3
table1
--
NULL
1
2
LEFT JOIN / IS NULL i NOT EXISTS zwróci 3 , NOT IN zwróci nic (ponieważ zawsze będzie oceniane jako FALSE lub NULL ).
W MySQL , w przypadku kolumny nie dopuszczającej wartości null, LEFT JOIN / IS NULL i NOT IN są trochę (kilka procent) bardziej wydajne niż NOT EXISTS . Jeśli kolumna dopuszcza wartość null, NOT EXISTS jest najbardziej wydajny (ponownie, niewiele).
W Oracle , wszystkie trzy zapytania dają te same plany (ANTI JOIN ).
W SQL Server , NOT IN / NOT EXISTS są bardziej wydajne, ponieważ LEFT JOIN / IS NULL nie można zoptymalizować do ANTI JOIN przez jego optymalizator.
W PostgreSQL , LEFT JOIN / IS NULL i NOT EXISTS są bardziej wydajne niż NOT IN , ponieważ są zoptymalizowane pod kątem Anti Join , podczas gdy NOT IN używa hashed subplan (lub nawet zwykły subplan jeśli podzapytanie jest zbyt duże do haszowania)