Zeilen filtern: WHERE vollständig

WHERE lässt nur Zeilen stehen, die eine Bedingung erfüllen. Hier geht es um kombinierte Bedingungen, Bereiche, Muster und den Umgang mit NULL.

Bedingungen verknüpfen

AND behält Zeilen, bei denen beide Seiten wahr sind, OR solche, bei denen eine davon wahr ist. Ausgeschrieben fragt das nach Bestellungen, die bezahlt oder versandt sind und mehr als 500 wert.

1

SELECT order_number, status, total
FROM orders
WHERE (status = 'paid' OR status = 'shipped')
  AND total > 500
ORDER BY total DESC
LIMIT 20;
In Planche ausführen

Ergebnis — erste 5 von 20 Zeilen

order_numberstatustotal
ORD-2025-002767shipped30906.66
ORD-2022-001901shipped28151.01
ORD-2023-001772paid26797.87
ORD-2024-001907shipped26648.91
ORD-2025-002847paid25837.57

Öffnet Planche in einem eigenen Browser-Tab, mit geladener Beispieldatenbank und dieser Abfrage im Editor. Alle Beispiele der Seite verwenden denselben Tab weiter, und ausgeführt wird erst, wenn Sie F9 drücken.

Die Klammern leisten echte Arbeit. Führen Sie dieselben Wörter ohne sie aus:

2

-- The same words without the brackets. AND binds tighter than OR,
-- so this reads as: paid (any total) OR shipped-and-over-500.
SELECT order_number, status, total
FROM orders
WHERE status = 'paid' OR status = 'shipped' AND total > 500
ORDER BY total DESC
LIMIT 20;
In Planche ausführen

Ergebnis — erste 5 von 20 Zeilen

order_numberstatustotal
ORD-2025-002767shipped30906.66
ORD-2022-001901shipped28151.01
ORD-2023-001772paid26797.87
ORD-2024-001907shipped26648.91
ORD-2025-002847paid25837.57

Sie bekommen eine andere Antwort, weil AND stärker bindet als OR – genau wie × stärker bindet als +. Ohne Klammern liest die Datenbank das als "bezahlt, in beliebiger Höhe, oder versandt und über 500", also kommt auch jede kleine bezahlte Bestellung zurück.

Einen von mehreren Werten treffen

Für eine Kette von ORs auf derselben Spalte gibt es IN.

3

SELECT order_number, status, total, ordered_at
FROM orders
WHERE status IN ('paid', 'shipped', 'delivered')
ORDER BY ordered_at DESC
LIMIT 20;
In Planche ausführen

Ergebnis — erste 5 von 20 Zeilen

order_numberstatustotalordered_at
ORD-2025-002480shipped6333.772025-12-28 23:52:14
ORD-2025-000505delivered2276.512025-12-28 11:16:39
ORD-2025-001581delivered2645.062025-12-28 06:12:38
ORD-2025-000995delivered2584.022025-12-28 05:47:53
ORD-2025-003219delivered561.482025-12-28 03:20:37

status IN ('paid', 'shipped', 'delivered') sagt, was drei ORs sagen würden, und sagt es einmal. NOT IN ist die Verneinung – mit einer scharfen Kante rund um NULL, die in der Lektion zu Unterabfragen einen eigenen Abschnitt bekommt.

Bereiche

BETWEEN a AND b ist die Kurzform für >= a AND <= b. Beide Enden sind eingeschlossen.

4

SELECT order_number, ordered_at, total
FROM orders
WHERE ordered_at BETWEEN '2025-01-01' AND '2025-01-31 23:59:59'
ORDER BY ordered_at
LIMIT 20;
In Planche ausführen

Ergebnis — erste 5 von 20 Zeilen

order_numberordered_attotal
ORD-2025-0034122025-01-01 00:18:522806.57
ORD-2025-0036162025-01-01 11:18:146955.62
ORD-2025-0015032025-01-01 23:43:345837.23
ORD-2025-0003172025-01-02 05:08:3215130.7
ORD-2025-0012982025-01-02 18:36:325045.04

Muster

LIKE vergleicht mit einem Muster, in dem % für eine beliebige Folge von Zeichen steht und _ für genau eines.

5

SELECT first_name, last_name, email
FROM customers
WHERE email LIKE '%@inbox.example'
ORDER BY last_name
LIMIT 20;
In Planche ausführen

Ergebnis — erste 5 von 20 Zeilen

first_namelast_nameemail
FreyaAhmedfreya.ahmed@inbox.example
HugoAhmedhugo.ahmed@inbox.example
JonasAhmedjonas.ahmed@inbox.example
KenjiAhmedkenji.ahmed@inbox.example
LiamAhmedliam.ahmed@inbox.example

Fehlende Werte

279 dieser Kunden haben keine Telefonnummer hinterlegt. Hier sind sie:

6

SELECT id, first_name, last_name, phone
FROM customers
WHERE phone IS NULL
LIMIT 20;
In Planche ausführen

Ergebnis — erste 5 von 20 Zeilen

idfirst_namelast_namephone
2MateoCostaNULL
9SvenSmithNULL
21LaylaFischerNULL
25FreyaNguyenNULL
28PriyaJangNULL

Und hier ist die Abfrage, die die meisten zuerst schreiben:

7

-- 279 customers have no phone number, and this finds none of them.
SELECT id, first_name, last_name, phone
FROM customers
WHERE phone = NULL;
In Planche ausführen

Keine Zeilen

Keine Zeilen. Kein Fehler, keine Warnung – ein leeres Raster.

NULL ist kein Wert, sondern die Abwesenheit eines Werts, deshalb kann kein Vergleich damit wahr sein. phone = NULL fragt "ist dieses unbekannte Ding gleich jenem unbekannten Ding", und die ehrliche Antwort lautet "unbekannt", was nicht wahr ist, also fällt die Zeile heraus. Auch NULL = NULL ist nicht wahr. Die einzigen Tests, die funktionieren, sind IS NULL und IS NOT NULL.

Was Sie jetzt können

Sie können fast jede Bedingung über eine Tabelle ausdrücken. Die verbleibende Grenze ist weiterhin, dass alles in einer Tabelle liegt – und die Fragen, die sich zu stellen lohnen, tun das meist nicht.

Selbst ausprobieren

  1. Kunden in Korea oder Japan, die Werbe-E-Mails zugestimmt haben (marketing_opt_in ist 1), sortiert nach Land und dann nach Nachname.

    Lösung anzeigen

    Lösung anzeigen

    SELECT first_name, last_name, country
    FROM customers
    WHERE country IN ('KR', 'JP')
      AND marketing_opt_in = 1
    ORDER BY country, last_name
    LIMIT 20;
    In Planche ausführen

    Ergebnis — erste 5 von 20 Zeilen

    first_namelast_namecountry
    AishaAhmedJP
    IsabellaAhmedJP
    IsabellaBrownJP
    TheoBrownJP
    NoraChoiJP

    IN spart ein OR, und Klammern braucht es hier nicht, weil nur ein AND zwei Bedingungen verbindet. Zwei Sortierschlüssel ergeben zuerst das Land, darin den Nachnamen.

  2. Bestellungen aus dem Jahr 2024, die storniert oder erstattet wurden, die ältesten zuerst.

    Lösung anzeigen

    Lösung anzeigen

    SELECT order_number, status, ordered_at
    FROM orders
    WHERE ordered_at >= '2024-01-01'
      AND ordered_at <  '2025-01-01'
      AND status IN ('cancelled', 'refunded')
    ORDER BY ordered_at
    LIMIT 20;
    In Planche ausführen

    Ergebnis — erste 5 von 20 Zeilen

    order_numberstatusordered_at
    ORD-2024-002563cancelled2024-01-02 11:41:56
    ORD-2024-002814cancelled2024-01-08 06:10:29
    ORD-2024-003123refunded2024-01-10 15:59:33
    ORD-2024-003024refunded2024-01-11 19:36:33
    ORD-2024-002258refunded2024-01-12 15:43:55

    Der halboffene Bereich ist der Punkt: >= '2024-01-01' AND < '2025-01-01' deckt das ganze Jahr ab, samt dem letzten Moment des 31. Dezember, den BETWEEN '2024-01-01' AND '2024-12-31' um Mitternacht abschneiden würde.