Unterabfragen benennen mit WITH
Unterabfragen in FROM können eine Abfrage schwer lesbar machen. Du musst sie von innen nach außen lesen, und mit jeder Unterabfrage verschachtelt sie sich tiefer. Mit WITH schreibst du die Unterabfrage zuerst, gibst ihr einen Namen und benutzt den Namen dann wie eine Tabelle:
WITH summen AS (
SELECT bestellung_id, SUM(menge * preis) AS gesamt
FROM positionen
GROUP BY bestellung_id
)
SELECT ROUND(AVG(gesamt), 2) AS durchschnitt_bestellung
FROM summen;| durchschnitt_bestellung |
|---|
| 42.0 |
Es ist die durchschnittliche Bestellung aus der vorigen Übung, aber jetzt liest es sich von oben nach unten: Berechne zuerst die Summen der Bestellungen und nenne sie summen; berechne dann ihren Durchschnitt. Der Teil WITH name AS (abfrage) heißt Common Table Expression, kurz CTE. Er gehört zu der Abfrage, die ihm folgt: Zusammen sind sie eine Anweisung mit einem Semikolon am Ende, und der Name summen existiert nur innerhalb dieser Anweisung.
Eine benannte Abfrage kann mehrfach benutzt werden. Die größte Bestellung ist die, deren Summe der größten Summe entspricht:
WITH summen AS (
SELECT bestellung_id, SUM(menge * preis) AS gesamt
FROM positionen
GROUP BY bestellung_id
)
SELECT bestellung_id, gesamt
FROM summen
WHERE gesamt = (SELECT MAX(gesamt) FROM summen);| bestellung_id | gesamt |
|---|---|
| 11 | 85 |
Ohne WITH müsstest du die Abfrage, die die Summen berechnet, zweimal schreiben, einmal in FROM und einmal in der Unterabfrage in WHERE.
Ein WITH kann mehrere Abfragen benennen, durch Kommas getrennt, wobei das Wort WITH nur am Anfang steht. Jede von ihnen kann die vor ihr benutzen. Hier behält bezahlte die bezahlten Bestellungen, bezahlte_summen berechnet ihre Summen, und die Hauptabfrage addiert sie:
WITH bezahlte AS (
SELECT *
FROM bestellungen
WHERE status = 'bezahlt'
),
bezahlte_summen AS (
SELECT p.bestellung_id, SUM(p.menge * p.preis) AS gesamt
FROM positionen AS p
JOIN bezahlte AS bz ON bz.id = p.bestellung_id
GROUP BY p.bestellung_id
)
SELECT COUNT(*) AS bezahlte_bestellungen, SUM(gesamt) AS umsatz
FROM bezahlte_summen;| bezahlte_bestellungen | umsatz |
|---|---|
| 28 | 1200 |
Typische Fehler: ein Komma nach der letzten benannten Abfrage, direkt vor dem SELECT der Hauptabfrage (near "SELECT": syntax error), und ein Semikolon nach ihrer schließenden Klammer, das die Anweisung beendet, bevor die Hauptabfrage begonnen hat (near ";": syntax error).
So schreibst du es:
Anweisungen
- 1
Die Abfrage im Editor findet den Monat mit dem höchsten Umsatz, berechnet aber den Umsatz jedes Monats zweimal, in zwei identischen Unterabfragen. Schreibe sie mit
WITHum: Nenne die Abfrage, die den Monatsumsatz berechnet,monatlichund benutze den Namen an beiden Stellen. Das Ergebnis bleibt gleich:monat umsatz 2024-12 160 - 2
Zeige darunter für jeden Kunden, der eine Bestellung aufgegeben und eine Bewertung geschrieben hat, den Namen, die Anzahl seiner Bestellungen als
anzahl_bestellungenund die Anzahl seiner Bewertungen alsanzahl_bewertungen. Zähle die Bestellungen jedes Kunden in einer benannten Abfrage und die Bewertungen in einer anderen, und verbinde beide dann mitkunden. (Würdest dubestellungenundbewertungendirekt mit den Kunden verbinden, würden sich die Zeilen vervielfachen: jede Bestellung mit jeder Bewertung.) Sortiere nach dem Namen:name anzahl_bestellungen anzahl_bewertungen Anna Fischer 2 2 Emma Becker 4 5 Greta Hoffmann 2 2 … … …