Oft müssen Abfragen formuliert werden, bei denen die Filterkriterien dynamisch festgelegt werden — die Liste der Werte wird vom Benutzer der Schnittstelle festgelegt, und fehlende Werte (NULL) sollten ebenfalls in das Ergebnis einfließen oder nicht. Solch eine Abfrage muss schnell auf großen Datenmengen arbeiten und semantisch korrekt in SQL sein.
Eine inkorrekte Kombination von Bedingungen IN, NOT IN und NULL-Prüfungen führt zu unerwarteten Ergebnissen, da in SQL der Ausdruck "NULL IN (...)" immer UNKNOWN zurückgibt und "NOT IN" zu einem leeren Ergebnis führen kann, wenn mindestens eines der Elemente in der Liste NULL ist. Die Leistung bei großen Datenmengen kann bei schlecht formulierten Bedingungen stark sinken.
Die korrekte Kombination sieht folgendermaßen aus:
SELECT * FROM sales WHERE region IN ('Moscow', 'Samara') OR region IS NULL;
SELECT * FROM sales WHERE (region NOT IN ('Moscow', 'Samara') OR region IS NULL);
SELECT * FROM sales WHERE region NOT IN ('Moscow', 'Samara') AND region IS NOT NULL;
Wesentliche Merkmale:
Was passiert, wenn man "WHERE field NOT IN ('a', NULL)" prüft?
Das Ergebnis ist immer leer, da jede Zeile mit NULL in der Liste verglichen wird, was UNKNOWN ergibt und alles herausfiltert.
Beispielcode:
SELECT * FROM test WHERE name NOT IN ('Ivan', NULL);
Gibt "IN (NULL,...)" einen Wert für Zeilen mit NULL zurück?
Nein. Der Ausdruck NULL IN (...) gibt immer UNKNOWN zurück, nicht TRUE.
Wie beschleunigt man die Filterung nach einer großen Werteliste?
Indizes verwenden und vorzugsweise einen JOIN mit einer temporären Tabelle machen, wenn die Liste groß ist (Hunderte/tausende von Werten) — das beschleunigt die Filterung im Vergleich zu einem langen IN.
Im Analysebericht wurde "WHERE city NOT IN ('London', field_2, NULL)" angewendet. Das Ergebnis — völlig leeres Ergebnis, niemand konnte lange die Ursache für die verlorenen Zeilen verstehen.
Vorteile:
Nachteile:
Im CRM wurde eine Liste von Kundenregionen ausgewählt und eine zusätzliche Schaltfläche "Unvollständige Werte einbeziehen" hinzugefügt. Logik des Filters:
... WHERE city IN ('SPB', 'NNov') OR city IS NULL
Vorteile:
Nachteile: