Wahrscheinlich bist du schon mal auf bedingte Ausdrücke in Programmiersprachen gestoßen: if-else, switch-case und ähnliche Konstrukte. In SQL gibt’s dafür das CASE-Statement. Damit kannst du direkt in der Abfrage Entscheidungen treffen: Wenn die Bedingung erfüllt ist, mach das eine, sonst mach was anderes.
Die CASE-Konstruktion ist besonders praktisch, wenn du mit Daten arbeitest, die NULL-Werte enthalten können. Der Syntax ist super simpel, fast wie ein Spickzettel, schau mal:
CASE
WHEN bedingung1 THEN ergebnis1
WHEN bedingung2 THEN ergebnis2
...
ELSE standard_ergebnis
END
Klingt logisch, oder? "Wenn das so ist, mach dies, sonst mach das." Kann man sich easy merken: "WHEN — das ist das Wenn, THEN — was zu tun ist, ELSE — was zu tun ist, wenn nix passt".
Beispiel: Produktklassifizierung
Stell dir vor, wir haben eine Tabelle products mit einer Spalte price, und wir wollen die Produkte je nach Preis in Gruppen einteilen.
| id | name | price |
|---|---|---|
| 1 | Magic Wand | 120 |
| 2 | Potion Set | 45 |
| 3 | Crystal Ball | 75 |
| 4 | Enchanted Map | NULL |
| 5 | Broomstick | 99 |
| 6 | Spell Book | 180 |
SELECT
name AS product_name,
price,
CASE
WHEN price IS NULL THEN 'Unbekannt'
WHEN price < 50 THEN 'Günstig'
WHEN price BETWEEN 50 AND 100 THEN 'Standard'
ELSE 'Premium'
END AS price_category
FROM products;
Was passiert hier?
- Wenn der Preis
pricebeim Produkt nicht angegeben ist (NULL), zeigen wir die Kategorie als'Unbekannt'an. - Wenn der Preis kleiner als 50 ist, gilt das Produkt als günstig
'Günstig'. - Wenn der Preis zwischen 50 und 100 liegt, landet es in der Kategorie
'Standard'. - Alles andere sind Premium-Produkte
'Premium'.
So sieht das Ergebnis aus:
| product_name | price | price_category |
|---|---|---|
| Magic Wand | 120 | Premium |
| Potion Set | 45 | Günstig |
| Crystal Ball | 75 | Standard |
| Enchanted Map | NULL | Unbekannt |
| Broomstick | 99 | Standard |
| Spell Book | 180 | Premium |
SQL liest die Zeilen der products-Tabelle wie ein Zauberer, wendet die Logik auf jede Zeile an und klassifiziert clever.
Arbeiten mit NULL in CASE WHEN
Oft gibt’s in den Daten fehlende Werte (hallo, NULL), und die willst du irgendwie ersetzen. Zum Beispiel haben wir eine Tabelle users mit einer Spalte email, und für User ohne E-Mail wollen wir 'Nicht angegeben' anzeigen.
| user_id | name | |
|---|---|---|
| 1 | Alex Lin | alex@example.com |
| 2 | Maria Chi | NULL |
| 3 | Anna Song | anna@magic.com |
| 4 | Otto Art | NULL |
| 5 | John Smith | john@wizard.org |
SELECT
user_id,
name,
CASE
WHEN email IS NULL THEN 'Nicht angegeben'
ELSE email
END AS email_address
FROM users;
| user_id | name | email_address |
|---|---|---|
| 1 | Alex Lin | alex@example.com |
| 2 | Maria Chi | Nicht angegeben |
| 3 | Anna Song | anna@magic.com |
| 4 | Otto Art | Nicht angegeben |
| 5 | John Smith | john@wizard.org |
SQL wirkt hier wie ein Schamane, der halbleere Zeilen wiederbelebt. Wenn die E-Mail fehlt, ersetzt er sie durch 'Nicht angegeben'. Wenn sie da ist, bleibt sie einfach stehen.
Bedingte Ausdrücke mit Zahlen
Manchmal willst du nicht nur Werte ersetzen, sondern auch neue Logik bauen. Zum Beispiel haben wir eine Tabelle students mit den Spalten score (Punktzahl) und name.
| name | score |
|---|---|
| Alex Lin | 95 |
| Maria Chi | 82 |
| Anna Song | 48 |
| Otto Art | NULL |
| John Smith | 67 |
| Zoe Black | 30 |
Wir wollen die Studenten als "Sehr gut", "Bestanden" und "Nicht bestanden" bewerten, je nach ihren Punkten.
SELECT
name AS student_name,
score,
CASE
WHEN score IS NULL THEN 'Keine Punktzahl'
WHEN score >= 90 THEN 'Sehr gut'
WHEN score >= 50 THEN 'Bestanden'
ELSE 'Nicht bestanden'
END AS performance_category
FROM students;
| student_name | score | performance_category |
|---|---|---|
| Alex Lin | 95 | Sehr gut |
| Maria Chi | 82 | Bestanden |
| Anna Song | 48 | Nicht bestanden |
| Otto Art | NULL | Keine Punktzahl |
| John Smith | 67 | Bestanden |
| Zoe Black | 30 | Nicht bestanden |
SQL verteilt die Studenten freundlich, wie ein strenger Prüfer: 90 Punkte und mehr — nur "Sehr gut", ab 50 — "Bestanden". Und wenn die Punkte nicht reichen... naja, du weißt schon.
Gruppierung und Umgang mit NULL
Mit Gruppen von Daten zu arbeiten ist ein weiteres Feld, wo CASE WHEN glänzt. Stell dir vor, wir haben eine Tabelle orders und wollen die Gesamtzahl der Bestellungen pro Status zählen, inklusive der mit NULL-Status.
| order_id | status |
|---|---|
| 1 | Completed |
| 2 | Pending |
| 3 | NULL |
| 4 | Shipped |
| 5 | Completed |
| 6 | NULL |
| 7 | Pending |
| 8 | Completed |
| 9 | Shipped |
| 10 | NULL |
SELECT
CASE
WHEN status IS NULL THEN 'Kein Status'
ELSE status
END AS order_status,
COUNT(*)
FROM orders
GROUP BY
CASE
WHEN status IS NULL THEN 'Kein Status'
ELSE status
END;
Diese Abfrage behandelt leere NULL-Status sauber und setzt 'Kein Status' ein, zählt dann die Gesamtzahl der Bestellungen pro Gruppe. Hier das Ergebnis:
| order_status | count |
|---|---|
| Completed | 3 |
| Pending | 2 |
| Shipped | 2 |
| Kein Status | 3 |
Praktische Cases: "Tricks" mit CASE WHEN
Beispiel 1: Sortieren mit NULL-Werten
Manchmal willst du NULL-Werte entweder ganz oben oder ganz unten in einer sortierten Liste anzeigen. Das ist oft bei Task-Listen so, wo wichtige Aufgaben oben stehen sollen und Aufgaben ohne Priorität (NULL) am Ende.
| task_id | task_name | priority |
|---|---|---|
| 1 | Fix bugs | 1 |
| 2 | Update documentation | 3 |
| 3 | Plan sprint | NULL |
| 4 | Code review | 2 |
| 5 | Organize meeting | NULL |
| 6 | Deploy release | 1 |
SELECT
task_name,
priority,
CASE
WHEN priority IS NULL THEN 1
ELSE 0
END AS priority_sort
FROM tasks
ORDER BY priority_sort ASC, priority ASC;
Hier haben wir eine "virtuelle" Spalte priority_sort hinzugefügt, die NULL-Werte nach unten schiebt und den Rest aufsteigend sortiert.
| task_name | priority | priority_sort |
|---|---|---|
| Deploy release | 1 | 0 |
| Fix bugs | 1 | 0 |
| Code review | 2 | 0 |
| Update documentation | 3 | 0 |
| Plan sprint | NULL | 1 |
| Organize meeting | NULL | 1 |
Beispiel 2: Berechnungen mit NULL
Jetzt stell dir vor, wir berechnen den Endbetrag einer Bestellung in der Tabelle orders, wo die Spalte discount den Rabatt enthält, der auch NULL sein kann, wenn es keinen gibt.
| order_id | total_price | discount |
|---|---|---|
| 101 | 100 | 10 |
| 102 | 200 | NULL |
| 103 | 150 | 15 |
| 104 | 120 | NULL |
| 105 | 80 | 5 |
Wir müssen NULL durch 0 ersetzen, damit die Berechnung nicht kaputtgeht.
SELECT
order_id,
total_price,
discount,
total_price -
CASE
WHEN discount IS NULL THEN 0
ELSE discount
END AS final_price
FROM orders;
| order_id | total_price | discount | final_price |
|---|---|---|---|
| 101 | 100 | 10 | 90 |
| 102 | 200 | NULL | 200 |
| 103 | 150 | 15 | 135 |
| 104 | 120 | NULL | 120 |
| 105 | 80 | 5 | 75 |
Dieser kleine Trick mit CASE sorgt dafür, dass NULL deine Mathe nicht ruiniert.
Für orderid = 101: discount = 10. finalprice = 100 - 10 = 90. Für orderid = 102: discount = NULL. CASE gibt 0 zurück. finalprice = 200 - 0 = 200. Für orderid = 103: discount = 15. finalprice = 150 - 15 = 135. Für orderid = 104: discount = NULL. CASE gibt 0 zurück. finalprice = 120 - 0 = 120. Für orderid = 105: discount = 5. finalprice = 80 - 5 = 75.
Beispiel 3: Benutzerstatus anzeigen
Im Alltag kommt es oft vor, dass du den Status eines Users anzeigen willst (zum Beispiel "Aktiv" oder "Wartend") oder auf fehlende Daten hinweisen willst. Zum Beispiel gibt’s in der Tabelle users eine Spalte last_login, wo das Datum des letzten Logins steht.
| user_id | name | last_login |
|---|---|---|
| 1 | Alex Lin | 2024-12-10 |
| 2 | Maria Chi | 2025-04-20 |
| 3 | Anna Song | NULL |
| 4 | Otto Art | 2025-05-01 |
| 5 | Liam Park | 2025-05-25 |
SELECT
user_id,
name,
CASE
WHEN last_login IS NULL THEN 'Nie eingeloggt'
WHEN last_login < CURRENT_DATE - INTERVAL '30 days' THEN 'Inaktiv'
ELSE 'Aktiv'
END AS user_status
FROM users;
Mit dieser Abfrage wird das Admin-System lebendig: User ohne Login heißen "Nie eingeloggt", die lange nicht da waren sind "Inaktiv". Die anderen sind aktiv!
| user_id | name | user_status |
|---|---|---|
| 1 | Alex Lin | Inaktiv |
| 2 | Maria Chi | Inaktiv |
| 3 | Anna Song | Nie eingeloggt |
| 4 | Otto Art | Inaktiv |
| 5 | Liam Park | Aktiv |
Typische Fehler und wie du sie vermeidest
Fehlendes ELSE: Wenn du kein ELSE angibst, gibt SQL einfach NULL zurück, wenn keine Bedingung passt. Das willst du meistens nicht. Also schreib lieber immer ein ELSE dazu, auch wenn du denkst, du hast alles abgedeckt.
CASE
WHEN condition THEN result
-- ELSE 'Standardwert' -- nicht vergessen!
END
Komplexe Bedingungen ohne Klammern: Wenn du mehrere Bedingungen mit AND, OR oder NOT hast, nutze immer Klammern. Sonst kann deine Abfrage plötzlich "falsch denken".
CASE
WHEN (column1 IS NOT NULL AND column2 > 5) THEN 'Gültig'
ELSE 'Ungültig'
END
Umgang mit NULL: Denk dran, NULL ist niemals gleich (=) irgendwas. Zum Beispiel:
CASE
WHEN column = NULL THEN 'Nope!' -- Fehler!
WHEN column IS NULL THEN 'Korrekt!' -- So ist’s richtig.
END
GO TO FULL VERSION