Verschachtle eine Abfrage in einer anderen, um mit einem Aggregat zu vergleichen, nach einer Menge zu filtern oder auf Existenz zu prüfen.
Diese Lektion in Kodokon öffnenEine Unterabfrage ist eine Abfrage, die in Klammern innerhalb einer anderen steht. In einer einzigen Anweisung beantwortet sie Fragen wie "die Bestellungen über dem Durchschnitt" oder "die Kunden mit mindestens einer Bestellung". Führe dieses Skript in sqliteonline.com oder sqlite3 aus, bevor du beginnst.
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL,
amount REAL NOT NULL
);
INSERT INTO customers (id, name) VALUES
(1, 'Alice'), (2, 'Karim'),
(3, 'Mina'), (4, 'Paulo');
INSERT INTO orders (id, customer_id, amount)
VALUES
(1, 1, 49.90), (2, 1, 15.00),
(3, 2, 120.50), (4, 2, 80.00),
(5, 3, 9.90), (6, 1, 200.00);In WHERE platziert, muss eine skalare Unterabfrage einen einzigen Wert zurückgeben: eine Zeile, eine Spalte. Die Engine berechnet sie zuerst und verwendet sie dann wie jede andere Konstante. Mit einem einfachen WHERE amount > AVG(amount), das in SQL verboten ist, geht das nicht.
SELECT id, customer_id, amount
FROM orders
WHERE amount > (
SELECT AVG(amount) FROM orders
);IN vergleicht eine Spalte mit der Menge der Werte, die die Unterabfrage zurückgibt. EXISTS prüft, ob die korrelierte Unterabfrage (sie verweist auf c.id, eine Spalte der äußeren Abfrage) mindestens eine Zeile zurückgibt: Die Engine hält an, sobald die erste Übereinstimmung gefunden ist.
SELECT name FROM customers
WHERE id IN (
SELECT customer_id FROM orders
WHERE amount > 100
);
SELECT c.name FROM customers AS c
WHERE EXISTS (
SELECT 1 FROM orders AS o
WHERE o.customer_id = c.id
);In FROM verhält sich eine Unterabfrage wie eine temporäre Tabelle, abgeleitete Tabelle genannt, und muss ein Alias erhalten. Sie ist das klassische Werkzeug, um in zwei Schritten zu aggregieren: zuerst eine Summe pro Kunde, dann der Durchschnitt dieser Summen.
SELECT ROUND(AVG(t.total), 2) AS avg_basket
FROM (
SELECT customer_id, SUM(amount) AS total
FROM orders
GROUP BY customer_id
) AS t;