Mise à jour :
Ces articles de mon blog décrivent plus en détail les différences entre les méthodes :
NOT INvsNOT EXISTSvsLEFT JOIN / IS NULL:SQL ServerNOT INvsNOT EXISTSvsLEFT JOIN / IS NULL:PostgreSQLNOT INvsNOT EXISTSvsLEFT JOIN / IS NULL:OracleNOT INvsNOT EXISTSvsLEFT JOIN / IS NULL:MySQL
Il existe trois façons de faire une telle requête :
-
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 )
Lorsque table1.common_id n'accepte pas la valeur null, toutes ces requêtes sont sémantiquement identiques.
Lorsqu'il est nullable, NOT IN est différent, puisque IN (et, par conséquent, NOT IN ) renvoie NULL lorsqu'une valeur ne correspond à rien dans une liste contenant un NULL .
Cela peut prêter à confusion mais peut devenir plus évident si nous rappelons la syntaxe alternative pour ceci :
common_id = ANY
(
SELECT common_id
FROM table1 t1
)
Le résultat de cette condition est un produit booléen de toutes les comparaisons de la liste. Bien sûr, un seul NULL la valeur donne le NULL result qui rend le résultat entier NULL aussi.
Nous ne pouvons jamais dire avec certitude que common_id n'est égal à aucun élément de cette liste, car au moins une des valeurs est NULL .
Supposons que nous ayons ces données :
common
--
1
3
table1
--
NULL
1
2
LEFT JOIN / IS NULL et NOT EXISTS renverra 3 , NOT IN ne renverra rien (car il évaluera toujours soit FALSE ou NULL ).
En MySQL , dans le cas d'une colonne non nullable, LEFT JOIN / IS NULL et NOT IN sont un peu (plusieurs pour cent) plus efficaces que NOT EXISTS . Si la colonne est nullable, NOT EXISTS est le plus efficace (encore une fois, pas beaucoup).
Dans Oracle , les trois requêtes donnent les mêmes plans (un ANTI JOIN ).
Dans SQL Server , NOT IN / NOT EXISTS sont plus efficaces, puisque LEFT JOIN / IS NULL ne peut pas être optimisé pour un ANTI JOIN par son optimiseur.
Dans PostgreSQL , LEFT JOIN / IS NULL et NOT EXISTS sont plus efficaces que NOT IN , puisqu'ils sont optimisés pour un Anti Join , tandis que NOT IN utilise hashed subplan (ou même un simple subplan si la sous-requête est trop grande pour être hachée)