Utiliser un EXISTS
expression :
WHERE NOT EXISTS (
SELECT FROM votes v -- SELECT list can be empty
WHERE v.some_id = base_table.some_id
AND v.user_id = ?
)
La différence
... entre NOT EXISTS()
(Ⓔ) et NOT IN()
(Ⓘ) est double :
-
Performances
Ⓔ est généralement plus rapide. Il arrête de traiter la sous-requête dès que la première correspondance est trouvée. Le manuel :
La sous-requête ne sera généralement exécutée qu'assez longtemps pour déterminer si au moins une ligne est renvoyée, pas jusqu'à la fin.
Ⓘ peut également être optimisé par le planificateur de requêtes, mais dans une moindre mesure puisque
NULL
la manipulation le rend plus complexe. -
Correctivité
Si l'une des valeurs résultantes dans l'expression de sous-requête est
NULL
, le résultat de Ⓘ estNULL
, alors que la logique commune attendraitTRUE
- et Ⓔ renverraTRUE
. Le manuel :Si tous les résultats par ligne sont inégaux ou nuls, avec au moins un nul, alors le résultat de
NOT IN
est nul.
Essentiellement, (NOT) EXISTS
est le meilleur choix dans la plupart des cas.
Exemple
Votre requête peut ressembler à ceci :
SELECT *
FROM questions q
WHERE NOT EXISTS (
SELECT FROM votes v
WHERE v.question_id = q.id
AND v.user_id = ?
);
Ne pas participer aux votes
dans la requête de base. Cela annulerait l'effort.
Outre NOT EXISTS
et NOT IN
il existe des options de syntaxe supplémentaires avec LEFT JOIN / IS NULL
et EXCEPT
. Voir :
- Sélectionner les lignes qui ne sont pas présentes dans un autre tableau