Ein Ergebnis abfragen
Am Ende der ersten Lektion hast du gelesen, dass das Ergebnis einer Abfrage auch eine Tabelle ist. Das heißt, du kannst es abfragen: Setze eine Unterabfrage in FROM, wo der Name einer Tabelle stünde.
Wie viel ist eine durchschnittliche Bestellung wert? Die Tabelle positionen hat eine Zeile für jedes Spiel einer Bestellung, also brauchst du zuerst die Summe jeder Bestellung:
SELECT bestellung_id, SUM(menge * preis) AS gesamt
FROM positionen
GROUP BY bestellung_id;| bestellung_id | gesamt |
|---|---|
| 1 | 25 |
| 2 | 35 |
| 3 | 40 |
| … | … |
Dann den Durchschnitt dieser Summen. AVG(SUM(menge * preis)) funktioniert nicht, denn Aggregatfunktionen lassen sich nicht verschachteln: Es endet mit misuse of aggregate function SUM(). Aber du kannst die Summen in einer Unterabfrage berechnen und ihren Durchschnitt in der äußeren Abfrage:
SELECT ROUND(AVG(gesamt), 2) AS durchschnitt_bestellung
FROM (
SELECT bestellung_id, SUM(menge * preis) AS gesamt
FROM positionen
GROUP BY bestellung_id
) AS summen;| durchschnitt_bestellung |
|---|
| 42.0 |
Die Unterabfrage läuft zuerst und macht eine temporäre Tabelle mit 30 Zeilen, eine für jede Bestellung, mit den Spalten bestellung_id und gesamt. Die äußere Abfrage behandelt sie wie jede andere Tabelle: Sie kann ihre Zeilen filtern, gruppieren und mit ihnen rechnen. Sie weiß nichts von positionen; sie sieht nur die Spalten der Unterabfrage, unter den Namen, die die Unterabfrage ihnen gegeben hat. Darum braucht jede berechnete Spalte der Unterabfrage einen Alias.
Nach der schließenden Klammer kommt der Name der Tabelle, hier AS summen. SQLite besteht nicht darauf, aber die meisten anderen Datenbanken schon, und du brauchst ihn immer, wenn du dich auf die Spalten der Unterabfrage beziehst, zum Beispiel in einem Join. Ja, du kannst auch eine Unterabfrage mit anderen Tabellen verbinden. Das sind die drei größten Bestellungen mit ihren Daten aus bestellungen:
SELECT b.id, b.bestellt_am, t.gesamt
FROM (
SELECT bestellung_id, SUM(menge * preis) AS gesamt
FROM positionen
GROUP BY bestellung_id
) AS t
JOIN bestellungen AS b ON b.id = t.bestellung_id
ORDER BY t.gesamt DESC, b.id
LIMIT 3;| id | bestellt_am | gesamt |
|---|---|---|
| 11 | 2024-09-30 | 85 |
| 14 | 2024-12-20 | 75 |
| 5 | 2024-04-02 | 65 |
Typischer Fehler: eine Spalte benutzen, die die Unterabfrage nicht liefert. Die äußere Abfrage sieht nur bestellung_id und gesamt, also endet preis oder menge darin mit no such column.
So schreibst du es:
Anweisungen
- 1
Wie viele Kunden haben eine Bestellung aufgegeben, wie viele zwei und so weiter? Zähle in einer Unterabfrage die Bestellungen jedes Kunden in
bestellungenalsanzahl_bestellungen. Gruppiere in der äußeren Abfrage ihre Zeilen nachanzahl_bestellungenund zähle sie alsanzahl_kunden. (Kunden, die nie bestellt haben, stehen nicht inbestellungen, werden also nicht gezählt.) Sortiere nachanzahl_bestellungen:anzahl_bestellungen anzahl_kunden 1 1 2 6 3 3 4 2 - 2
Zeige darunter die Spiele, die mehr kosten als der Durchschnittspreis ihres Genres: den Titel, das Genre, den Preis und den Durchschnittspreis des Genres, auf eine Nachkommastelle gerundet, als
genre_durchschnitt. Berechne den Durchschnitt jedes Genres in einer Unterabfrage und verbinde sie über das Genre mitspiele. Sortiere nach Genre, dann nach Titel:titel genre preis genre_durchschnitt Robot Rebellion Action 40 32.5 Star Pilots Action 35 32.5 Mystery Manor Adventure 25 20.0 … … … …