Mettre à jour:
Ces articles de mon blog décrivent plus en détail les différences entre les méthodes:
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
)
Quand table1.common_idn'est pas nullable, toutes ces requêtes sont sémantiquement identiques.
Quand il est nullable, NOT INest différent, puisque IN(et, par conséquent, NOT IN) retourne NULLquand une valeur ne correspond à rien dans une liste contenant un NULL.
Cela peut être déroutant 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 dans la liste. Bien sûr, une seule NULLvaleur donne le NULLrésultat qui rend également le résultat entier NULL.
Nous ne pouvons jamais dire avec certitude que ce common_idn'est égal à rien de cette liste, car au moins une des valeurs l'est NULL.
Supposons que nous ayons ces données:
common
--
1
3
table1
--
NULL
1
2
LEFT JOIN / IS NULLet NOT EXISTSretournera 3, NOT INne retournera rien (car il sera toujours évalué à l'un FALSEou l' autre NULL).
Dans MySQL, en cas de colonne non nullable, LEFT JOIN / IS NULLet NOT INsont un peu plus efficaces (plusieurs pour cent) que NOT EXISTS. Si la colonne est nullable, NOT EXISTSc'est le plus efficace (encore une fois, pas beaucoup).
Dans Oracle, les trois requêtes génèrent les mêmes plans (an ANTI JOIN).
Dans SQL Server, NOT IN/ NOT EXISTSsont plus efficaces, car LEFT JOIN / IS NULLne peuvent pas être optimisés à un ANTI JOINpar son optimiseur.
Dans PostgreSQL, LEFT JOIN / IS NULLet NOT EXISTSsont plus efficaces que NOT IN, sine, ils sont optimisés pour un Anti Join, while NOT INuses hashed subplan(ou même un plain subplansi la sous-requête est trop grande pour le hachage)