Lesbare SQL-Abfragen mit CTEs – die WITH-Klausel
Verschachtelte Unterabfragen werden schnell unleserlich. Mit einer Common Table Expression (WITH … AS) gibst du einer Zwischenabfrage einen Namen und liest sie von oben nach unten wie einen kleinen Rechenweg. Ich zeige ein Beispiel mit Zwischenschritt.
Sobald eine Abfrage einen Zwischenschritt braucht, landen viele bei verschachtelten Unterabfragen – und die liest nach zwei Ebenen niemand mehr gern. Sauberer geht das mit einer CTE (Common Table Expression), also der WITH-Klausel: Du gibst dem Zwischenergebnis einen Namen und benutzt es danach wie eine Tabelle.
Vorher: verschachtelte Unterabfrage
SELECT name, umsatz
FROM (
SELECT kunde_id, SUM(betrag) AS umsatz
FROM bestellungen
GROUP BY kunde_id
) t
JOIN kunden k ON k.id = t.kunde_id
WHERE t.umsatz > 1000;Nachher: mit WITH
WITH kunden_umsatz AS (
SELECT kunde_id, SUM(betrag) AS umsatz
FROM bestellungen
GROUP BY kunde_id
)
SELECT k.name, u.umsatz
FROM kunden_umsatz u
JOIN kunden k ON k.id = u.kunde_id
WHERE u.umsatz > 1000;Der obere Block berechnet den Umsatz pro Kunde und heißt kunden_umsatz. Der untere Teil liest sich dann geradlinig – erst der Zwischenschritt, dann das Ergebnis. Genau derselbe Rechenweg, nur von oben nach unten statt von innen nach außen.
Mehrere Schritte hintereinander
Der eigentliche Gewinn kommt bei mehreren Zwischenschritten – du reihst sie mit Komma aneinander:
WITH pro_kunde AS (
SELECT kunde_id, SUM(betrag) AS umsatz
FROM bestellungen GROUP BY kunde_id
),
schnitt AS (
SELECT AVG(umsatz) AS avg_umsatz FROM pro_kunde
)
SELECT k.name, p.umsatz
FROM pro_kunde p, schnitt s
JOIN kunden k ON k.id = p.kunde_id
WHERE p.umsatz > s.avg_umsatz; -- über dem DurchschnittJeder Schritt hat einen Namen, jeder baut auf dem vorherigen auf. Das ist wartbar und beim Lesen sofort verständlich.
CTEs gibt es in SQLite (3.8.3+), PostgreSQL, MySQL 8+ und SQL Server. Wenn du ein Projekt mit sauberer Datenbank und nachvollziehbaren Auswertungen brauchst, baue ich dir das – meld dich über bymw.de.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
WITH RECURSIVE – Kategoriebäume und Kommentar-Threads in einer einzigen Abfrage
Kategorien mit Unterkategorien, Kommentare mit Antworten, Ordner in Ordnern: Die meisten holen sich so etwas mit einer Schleife und einer Abfrage pro Ebene. Eine rekursive CTE holt den ganzen Baum in einem Rutsch – inklusive Tiefe und Pfad.
Wie viel mehr als gestern? Differenz zur Vorzeile mit LAG() in SQL
„Wie viele Besucher heute im Vergleich zu gestern?" – der Reflex ist ein Self-Join auf die Vorzeile. Mit der Fensterfunktion LAG() bekommst du den Wert der vorherigen Zeile direkt daneben, ohne die Tabelle ein zweites Mal anzufassen.
UNION vs. UNION ALL – zwei Abfragen zusammenlegen, ohne Zeilen zu verlieren
UNION entfernt Duplikate. Das klingt hilfreich, kostet aber eine komplette Sortierung – und wirft dir stillschweigend echte Zeilen weg, die zufällig identisch aussehen. UNION ALL ist fast immer die richtige Wahl.