Il est souvent nécessaire de formuler des requêtes où les critères de filtrage sont définis dynamiquement — la liste des valeurs est spécifiée par l'utilisateur de l'interface, et les valeurs manquantes (NULL) doivent également être en mesure de figurer ou non dans le résultat. Une telle requête doit fonctionner rapidement sur de grands volumes et être correcte du point de vue de la sémantique SQL.
Une combinaison incorrecte des conditions IN, NOT IN et vérification de NULL conduit à des résultats inattendus car, dans SQL, l'expression "NULL IN (...)" retourne toujours UNKNOWN, et "NOT IN" peut entraîner un résultat vide si au moins un des éléments de la liste est NULL. La performance sur de grandes données peut chuter brusquement si la condition est mal écrite.
Une bonne combinaison ressemble à ceci :
SELECT * FROM sales WHERE region IN ('Moscou','Samara') OR region IS NULL;
SELECT * FROM sales WHERE (region NOT IN ('Moscou','Samara') OR region IS NULL);
SELECT * FROM sales WHERE region NOT IN ('Moscou','Samara') AND region IS NOT NULL;
Caractéristiques clés :
Que se passera-t-il si nous vérifions "WHERE field NOT IN ('a', NULL)"?
Le résultat est toujours vide, car toute ligne est comparée à NULL dans la liste, ce qui donne UNKNOWN et filtre tout.
Exemple de code :
SELECT * FROM test WHERE name NOT IN ('Ivan', NULL);
L'expression "IN (NULL,...)" donnera-t-elle une valeur pour les lignes avec NULL?
Non. L'expression NULL IN (...) retourne toujours UNKNOWN, et non TRUE.
Comment accélérer le filtrage sur une grande liste de valeurs?
Utiliser des index et de préférence appliquer JOIN avec une table temporaire si la liste est grande (centaines/ milliers de valeurs) — cela accélère le filtrage par rapport à un long IN.
Dans un rapport analytique, on a appliqué "WHERE city NOT IN ('Londres', field_2, NULL)". Résultat — total vide, personne ne pouvait comprendre pourquoi des lignes étaient perdues.
Avantages :
Inconvénients :
Dans le CRM, une liste de régions clients a été sélectionnée et un bouton supplémentaire "Inclure les valeurs non renseignées" a été ajouté. Logique de filtrage :
... WHERE city IN ('SPB','NNov') OR city IS NULL
Avantages :
Inconvénients :