Filtere nach der Aggregation mit HAVING und pivotiere deine Daten mit CASE WHEN innerhalb von Aggregatfunktionen.
Diese Lektion in Kodokon öffnenDu kennst GROUP BY bereits. Dieses Modul geht das an, was eine korrekte Abfrage von einer professionellen unterscheidet: das Filtern nach der Aggregation, bedingte Aggregate und ein solides Verständnis der Auswertungsreihenfolge. Zum Üben öffnest du sqliteonline.com (SQLite-Engine) oder startest sqlite3 in einem Terminal: Jede Lektion liefert dir die nötigen CREATE TABLE- und INSERT-Anweisungen. Kopiere diesen Datensatz, bevor du die Beispiele ausführst.
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer TEXT NOT NULL,
category TEXT NOT NULL,
amount REAL NOT NULL,
status TEXT NOT NULL
);
INSERT INTO orders (customer, category, amount, status)
VALUES
('alice', 'books', 42.0, 'paid'),
('alice', 'games', 55.0, 'paid'),
('alice', 'books', 18.5, 'refunded'),
('bruno', 'games', 70.0, 'paid'),
('bruno', 'books', 12.0, 'paid'),
('chloe', 'games', 95.0, 'paid'),
('chloe', 'books', 30.0, 'paid'),
('david', 'books', 8.0, 'refunded');Die logische Auswertungsreihenfolge ist der Schlüssel: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY. WHERE filtert Zeilen vor der Gruppierung; HAVING filtert Gruppen, nachdem die Aggregate berechnet wurden. Genau deshalb ist WHERE SUM(amount) > 90 unzulässig: In der WHERE-Phase existiert noch keine Summe. Hier behalten wir nur Kundinnen und Kunden, deren bezahlte Summe 90 übersteigt (erwartet: alice und chloe).
SELECT customer,
COUNT(*) AS nb_orders,
SUM(amount) AS total
FROM orders
WHERE status = 'paid'
GROUP BY customer
HAVING SUM(amount) > 90;Das zweite unverzichtbare Muster ist das bedingte Aggregat. Indem du ein CASE WHEN in SUM oder COUNT einschiebst, berechnest du mehrere Kennzahlen in einem einzigen Durchlauf über die Tabelle, wo ein Anfänger drei getrennte Abfragen ausführen würde. Das ist die Standardtechnik, um Zeilen in Spalten zu pivotieren.
SELECT customer,
SUM(CASE WHEN category = 'books'
THEN amount ELSE 0 END) AS books_total,
SUM(CASE WHEN category = 'games'
THEN amount ELSE 0 END) AS games_total
FROM orders
WHERE status = 'paid'
GROUP BY customer;