Übung 7: Nordwind-Datenbank
Lösung geprüft
Die Aufgabe der heutigen Stunde ist die siebte Übung – vermischte Aufgaben zur Nordwind-Datenbank! Hier kommt nichts Neues mehr dazu, es geht darum, alles aus den sechs Lektionen zusammen zu benutzen. Genau so sieht auch die Klausur aus.
a) Bearbeiten Sie die Übung 7
Zusatzaufgabe: Erstellen Sie eine Datenbank-Anfrage zur Beantwortung der folgenden Frage: Welche Kategorie hat den meisten Umsatz erzielt?
Die Zusatzaufgabe
kategorien, artikel und
bestelldetails. Heißen sie bei euch anders, tausch nur die
Namen aus.
-- Welche Kategorie hat den meisten Umsatz erzielt?
-- @meininfokurs.cmrg.site
SELECT k.kategoriename,
SUM(bd.einzelpreis * bd.anzahl) AS Umsatz
FROM kategorien AS k
INNER JOIN artikel AS a ON k.kategorie_id = a.kategorie_id
INNER JOIN bestelldetails AS bd ON a.artikel_id = bd.artikel_id
GROUP BY k.kategorie_id, k.kategoriename
ORDER BY Umsatz DESC
LIMIT 1;
Wie man auf so eine Abfrage kommt
Nicht von vorne anfangen zu tippen, sondern die Frage zerlegen:
- Was will ich sehen? Den Kategorienamen und einen Umsatz → das kommt ins
SELECT. - Wo stehen diese Daten? Der Name in
kategorien, die Preise inbestelldetails. Dazwischen liegtartikel→ zweiJOINs. - Was ist „Umsatz"? Einzelpreis mal Anzahl, über alle Positionen aufsummiert →
SUM(einzelpreis * anzahl). - Pro was? Pro Kategorie →
GROUP BY. - „Den meisten"? Absteigend sortieren und den ersten nehmen →
ORDER BY … DESC LIMIT 1.
Die dritte Zeile ist die, die man am ehesten falsch macht. „Umsatz" ist
keine Spalte, die irgendwo steht – man muss sie ausrechnen. Und zwar
innerhalb von SUM, nicht außerhalb:
SUM(bd.einzelpreis * bd.anzahl) -- richtig: pro Zeile rechnen, dann addieren
SUM(bd.einzelpreis) * SUM(bd.anzahl) -- FALSCH: ergibt voellig andere Zahlen
Die zweite Variante multipliziert die Summe aller Preise mit der Summe aller Stückzahlen. Das ist eine Zahl ohne jede Bedeutung – und sie sieht auf den ersten Blick trotzdem plausibel aus.
Warum die Kategorie-ID mit ins GROUP BY gehört
GROUP BY k.kategorie_id, k.kategoriename – warum beides?
Weil es theoretisch zwei Kategorien mit demselben Namen geben könnte.
Gruppiert man nur nach dem Namen, würden deren Umsätze zusammengerechnet.
Die ID ist der Primärschlüssel und damit garantiert eindeutig.
Wenn man alle Kategorien sehen will
-- Dasselbe ohne LIMIT: die vollstaendige Rangliste
SELECT k.kategoriename,
SUM(bd.einzelpreis * bd.anzahl) AS Umsatz
FROM kategorien AS k
INNER JOIN artikel AS a ON k.kategorie_id = a.kategorie_id
INNER JOIN bestelldetails AS bd ON a.artikel_id = bd.artikel_id
GROUP BY k.kategorie_id, k.kategoriename
ORDER BY Umsatz DESC;
Das ist meistens die bessere Abfrage: man sieht nicht nur den Sieger,
sondern auch, wie deutlich der Abstand ist. Und wenn zwei Kategorien
gleichauf liegen, würde LIMIT 1 eine davon willkürlich
unterschlagen.
Was in Übung 7 zusammenkommt
Der Rückblick im OneNote listet genau auf, was aus welcher Lektion gebraucht wird:
| Lektion | Inhalt |
|---|---|
| 1 | WHERE, BETWEEN, LIKE, DISTINCT, ORDER BY, LIMIT |
| 2 | SUM, COUNT, AVG, MAX, MIN |
| 3 | INNER JOIN … ON |
| 4 | GROUP BY, HAVING |
| 5 | geschachtelte SELECT mit IN |
| 6 | INSERT, UPDATE, DELETE, CREATE TABLE |
Die Zusatzaufgabe allein benutzt Bausteine aus vier dieser sechs Lektionen. Wenn du die hinbekommst, hast du den SQL-Teil verstanden.