SQL IN: zeilenweise Filterung per Werteliste

Der SQL-IN-Operator prüft, ob ein Wert mit einem Element aus einer Liste übereinstimmt. Ein SQL-WHERE-IN-Prädikat ersetzt lange OR-Ketten, wenn nach einer bekannten Menge diskreter Werte gefiltert wird, etwa Statuscodes, Kategorienamen oder Regions-IDs. Nutze eine SQL-WHERE-IN-Liste, wenn die Werte vorher feststehen und die Bedingung auch bei wachsender Menge lesbar bleiben soll.

SQL IN Beispiel für Listenabgleich

Ausgabe:

Die Ausgabe erscheint hier...

Ausgabe:

+-------------+--------------+
| name        | kategorie    |
+-------------+--------------+
| Maus        | elektronik   |
| Notizbuch   | schreibwaren |
| Radiergummi | schreibwaren |
| Tastatur    | elektronik   |
+-------------+--------------+
4 row(s)

So funktioniert dieses Beispiel

  1. CREATE TABLE und INSERT füllen eine Tabelle produkte mit fünf Zeilen über drei Kategorien.
  2. WHERE kategorie IN ('elektronik', 'schreibwaren') trifft auf jede Zeile zu, deren kategorie einem der gelisteten Werte entspricht. Logisch ist das gleichbedeutend mit kategorie = 'elektronik' OR kategorie = 'schreibwaren'.
  3. Die Zeile moebel wird ausgeschlossen, weil ihre kategorie nicht in der Liste steht.
  4. ORDER BY name sorgt für deterministische Ausgabe.

IN mit einer Literalliste ist äquivalent zu verketteten OR-Vergleichen, skaliert aber besser bei wachsenden Mengen: Ein neuer Wert bedeutet einen weiteren Listeneintrag statt einer zusätzlichen OR-Klausel.

Was ist der SQL-IN-Operator?

Der SQL-IN-Operator ist eine Kurzform für mehrere Gleichheitsvergleiche, die mit OR verknüpft sind. WHERE x IN (a, b, c) ist logisch identisch zu WHERE x = a OR x = b OR x = c. In der dreiwertigen SQL-Logik liefert IN false, wenn kein Listenelement passt und kein Element NULL ist. Wenn ein Element NULL ist und kein exakter Treffer existiert, ist das Ergebnis unknown; in einer WHERE-Klausel wird die Zeile dann herausgefiltert.

Umgang mit einer leeren SQL-WHERE-IN-Liste

Die meisten Datenbanken lehnen WHERE col IN () als Syntaxfehler ab, was oft bei dynamisch erzeugten SQL-WHERE-IN-Listen auftritt. Behandle den leeren Fall explizit: Filter weglassen oder ein immer-falsches Prädikat wie WHERE 1 = 0 erzwingen, wenn eine leere Liste keine Zeilen zurückgeben soll.

SQL NOT IN und die NULL-Falle

SQL NOT IN invertiert die Prüfung: true wird nur geliefert, wenn der Wert von jedem Element in der Liste verschieden ist. Ein einziges NULL in der Liste kann das Ergebnis auf unknown kippen, weil x <> NULL immer unknown ist und WHERE unknown wie false behandelt:

-- Gibt 0 Zeilen zurück: NULL macht das Prädikat UNKNOWN
SELECT name
FROM produkte
WHERE kategorie NOT IN ('elektronik', NULL);

Wenn die Liste aus einer Unterabfrage kommt, filtere NULL-Werte in der Unterabfrage heraus oder nutze NOT EXISTS für NULL-sichere Semantik.

IN mit Unterabfragen

IN akzeptiert auch eine Unterabfrage statt einer Literalliste. Konzeptionell erzeugt die Unterabfrage eine Wertemenge, und die äußere Abfrage prüft die Zugehörigkeit:

SELECT name FROM produkte
WHERE kategorie IN (
  SELECT kategorie FROM produkte WHERE name LIKE '%buch%'
);

Bei kleinen, nicht korrelierten Unterabfragen funktioniert das gut. Wenn die Unterabfrage viele Zeilen zurückliefert oder Korrelation enthält, sind ein EXISTS-Prädikat oder ein JOIN oft performanter, weil der Optimizer Semi-Join-Strategien anwenden kann.

IN vs EXISTS vs JOIN

AnsatzVerwenden, wenn …
IN (list)Nach einer kleinen, bekannten Menge von Literalwerten gefiltert wird
IN (subquery)Zugehörigkeit zu einer kleinen, nicht-nullbaren Ergebnismenge geprüft wird
EXISTS (subquery)Eine korrelierte Prüfung oder nullbare Fremdschlüssel vorliegen
JOINSpalten aus beiden Tabellen in der Ausgabe nötig sind
BETWEENWerte einen kontinuierlichen Bereich statt diskreter Elemente bilden

Regel: Verwende IN für diskrete Wertemengen. Wechsle zu EXISTS, wenn die Unterabfrage korreliert oder nullable ist. Nutze JOIN, wenn Daten von beiden Seiten gebraucht werden.

Hinweise zur Performance

IN auf einer indizierten Spalte ist sargable, der Optimizer kann also für jeden Listenwert Index-Lookups ausführen. Manche Engines sortieren Literal-IN-Listen intern für eine binäre Suche. Sehr große Literallisten (Hunderte Werte) können Query-Parsing und Plan-Erzeugung verlangsamen; lade diese Werte stattdessen in eine temporäre Tabelle und verwende JOIN.

FAQ

Ist SQL IN dasselbe wie mehrere OR-Bedingungen?

Logisch ja. WHERE x IN (1, 2, 3) entspricht WHERE x = 1 OR x = 2 OR x = 3. Der Optimizer erzeugt für beide Formen meist denselben Ausführungsplan, aber IN ist kürzer und bei wachsenden Listen leichter zu warten.

Warum liefert NOT IN keine Zeilen, wenn die Unterabfrage NULL enthält?

NOT IN expandiert zu einer Kette aus AND-Vergleichen: x <> a AND x <> b AND x <> NULL. Da x <> NULL immer unknown ist, wird der gesamte Ausdruck nie true. Filtere NULL-Werte in der Unterabfrage heraus oder nutze NOT EXISTS, um das zu vermeiden.

Kann ich IN mit einer Unterabfrage verwenden?

Ja. WHERE col IN (SELECT col FROM other_table) prüft die Zugehörigkeit zur Ergebnismenge der Unterabfrage. Für kleine, nicht-nullbare Ergebnismengen ist das effizient. Bei großen oder nullbaren Mengen geben EXISTS oder JOIN dem Optimizer oft mehr Spielraum.