Joins und Gruppen
Joins und GROUP BY passen gut zusammen: Der Join legt die Daten aus mehreren Tabellen in Zeilen, und GROUP BY fasst sie zusammen. Wie viele Exemplare der Spiele jedes Genres haben Kunden bestellt? Die Mengen stehen in positionen, die Genres in spiele:
SELECT s.genre, SUM(p.menge) AS exemplare
FROM positionen AS p
JOIN spiele AS s ON p.spiel_id = s.id
GROUP BY s.genre
ORDER BY exemplare DESC, s.genre;| genre | exemplare |
|---|---|
| Action | 8 |
| RPG | 7 |
| Strategie | 7 |
| … | … |
Der Join gibt eine Zeile für jede Position, mit dem Genre ihres Spiels. GROUP BY bildet dann für jedes Genre eine Gruppe, und SUM addiert die Mengen in jeder Gruppe.
Mit Geld funktioniert es genauso. Eine Position hat ihre Menge mal den Preis eingebracht, den der Kunde für ein Exemplar gezahlt hat: p.menge * p.preis. Nicht s.preis: Das ist der Preis im Katalog, und in einem Angebot zahlen Kunden weniger. Das Geld, das eine Gruppe eingebracht hat, ihr Umsatz, ist dann SUM(p.menge * p.preis): SUM berechnet den Ausdruck für jede Zeile der Gruppe und addiert die Ergebnisse.
Wenn du nach etwas gruppierst, das einen Namen hat, wie ein Kunde oder ein Spiel, gruppiere nach seiner id und nimm den Namen auch in GROUP BY auf: GROUP BY k.id, k.name. Zwei Kunden können denselben Namen haben, und GROUP BY k.name allein würde sie in eine Gruppe stecken, als wären sie eine Person. Dank des Namens in GROUP BY kannst du ihn in SELECT zeigen: Jede Gruppe hat eine id, also auch einen Namen. Wie viele Bewertungen hat jeder Kunde geschrieben, und wie viele Sterne gibt er durchschnittlich?
SELECT k.name, COUNT(*) AS anzahl_bewertungen, ROUND(AVG(bw.sterne), 1) AS durchschnitt
FROM bewertungen AS bw
JOIN kunden AS k ON bw.kunde_id = k.id
GROUP BY k.id, k.name
ORDER BY anzahl_bewertungen DESC, k.name;| name | anzahl_bewertungen | durchschnitt |
|---|---|---|
| Emma Becker | 5 | 4.4 |
| Anna Fischer | 2 | 3.5 |
| Greta Hoffmann | 2 | 3.5 |
| … | … | … |
Eine erstattete Bestellung hat nichts eingebracht, der Umsatz sollte also nur die bezahlten zählen. Der Status steht in bestellungen: Verbinde die Tabelle auch und behalte mit WHERE nur die bezahlten Bestellungen. WHERE läuft vor GROUP BY, die Zeilen erstatteter Bestellungen sind also weg, bevor etwas addiert wird. HAVING wählt dann Gruppen aus, wie du aus der Lektion über das Gruppieren weißt.
Typischer Fehler: SUM(menge * preis) ohne die Aliase. Wenn spiele in der Abfrage ist, ist preis mehrdeutig, und du bekommst einen Fehler. SUM(p.menge * s.preis) ist schlimmer: Es läuft, addiert aber die Preise aus dem Katalog, und das Angebot verschwindet aus dem Umsatz.
So schreibst du es:
Anweisungen
- 1
Zeige den Umsatz jedes Spiels aus bezahlten Bestellungen: den
titelund den Umsatz alsumsatz. Du brauchst drei Tabellen:positionen,bestellungen(für den Status) undspiele. Sortiere die Spiele nach dem Umsatz vom höchsten Wert, dann nach dem Titel:titel umsatz Knight's Oath 180 Dragon Forge 160 Goal Rush 100 Ice Hockey Pro 90 Turbo Karts 90 Zombie Town 80 … … - 2
Zeige darunter, wie viele bezahlte Bestellungen jeder Kunde aufgegeben hat: den
nameund die Zahl alsanzahl_bestellungen, sortiert nachanzahl_bestellungenvom höchsten Wert, dann nachname:name anzahl_bestellungen Emma Becker 4 Olivia Braun 4 Lukas Neumann 3 Noah Winter 3 Anna Fischer 2 … … - 3
Und welche Kunden haben in bezahlten Bestellungen mehr als 100 € ausgegeben? Zeige den
nameund das ausgegebene Geld alsausgegeben, nur für die Kunden, die mehr als 100 ausgegeben haben, sortiert nachausgegebenvom höchsten Wert, dann nachname:name ausgegeben Emma Becker 200 Lukas Neumann 150 Noah Winter 150 Olivia Braun 150