Zum Inhalt
wannacode

Unterabfragen

Kurz gesagt: Eine Unterabfrage ist ein SELECT in einer anderen Abfrage, das einen Wert oder eine Liste für WHERE liefert und mit IN, EXISTS oder NOT EXISTS benutzt wird.

Problem

Über dem Durchschnitt

Die Shopleitung will die Produkte sehen, die mehr kosten als der Durchschnittspreis im Shop. Du kennst schon zwei Abfragen: Die eine findet den Durchschnittspreis, die andere sucht Produkte über einer bestimmten Zahl.

Du könntest die erste ausführen, die Zahl kopieren und die zweite ausführen. Aber morgen sind die Preise andere, und die kopierte Zahl ist veraltet.

Die Idee

Unterabfrage

Zuerst der Durchschnittspreis:

SQLDatenbank: Shop

Jetzt dieselbe Abfrage, in Klammern, anstelle der Zahl:

SQLDatenbank: Shop

Eine Abfrage in Klammern innerhalb einer anderen Abfrage heißt Unterabfrage (Subquery). Die Datenbank führt sie zuerst aus, bekommt 7,036 und prüft dann jedes Produkt mit price > 7.036. Es kommen acht Produkte heraus.

Diese Unterabfrage liefert eine Zahl, deshalb steht sie dort, wo eine Zahl stehen würde.

Genauer, für Neugierige

Wenn eine Unterabfrage in einem Vergleich mehrere Zeilen liefert, nimmt SQLite stillschweigend die erste. Kategorie 8 („Küche“) hat drei Produkte, aber die Abfrage vergleicht nur mit einem davon:

SQLDatenbank: Shop

Welche Zeile „die erste“ ist, wird nicht versprochen. PostgreSQL und SQL Server geben in diesem Fall einen Fehler aus: Die Unterabfrage habe mehr als eine Zeile geliefert. Wenn eine Unterabfrage mehrere Zeilen liefern kann, nimm IN.

Probier es aus

Teurer als der Kaschkawal

Zeige Name und Preis der Produkte, die mehr kosten als der Kaschkawal. Tippe seinen Preis nicht von Hand ein: Hol ihn mit einer Unterabfrage.

SQLDatenbank: Shop

Die Idee

IN mit einer Liste aus einer Abfrage

IN mit einer von Hand getippten Liste kennst du schon: city IN ('Varna', 'Burgas'). Die Liste kann auch aus einer Unterabfrage kommen.

Welche Kunden haben im Oktober 2026 bestellt? Ihre Nummern stehen in orders, ihre Namen in customers:

SQLDatenbank: Shop

Die Unterabfrage liefert die Nummern der Kunden mit Bestellungen ab dem 1. Oktober. Die äußere Abfrage zeigt die Kunden, deren id in dieser Liste steht.

Unterabfragen lassen sich ineinander verschachteln. Jeder Schritt ist eine eigene Abfrage, die du für sich ausführen und prüfen kannst.

Probier es aus

Wer Kaffee kauft

Der Kaffeelieferant bringt eine neue Sorte heraus und will die Leute anschreiben, die schon „Kaffeebohnen“ gekauft haben. Zeige ihre Namen. Das Feld beginnt mit dem ersten Schritt: der Produktnummer.

SQLDatenbank: Shop

Die Idee

EXISTS

Manchmal ist dir egal, was die Unterabfrage liefert, sondern nur, ob sie überhaupt etwas liefert. Welche Kunden haben noch keine Bestellung?

SQLDatenbank: Shop

EXISTS (…) ist wahr, wenn die Unterabfrage mindestens eine Zeile liefert. NOT EXISTS ist das Gegenteil. Was in der Unterabfrage nach SELECT steht, ist egal, deshalb steht dort SELECT 1.

Hier schaut die Unterabfrage auf die äußere Zeile: o.customer_id = c.id, wobei c der Kunde ist, den die äußere Abfrage gerade prüft. Das ist eine neue Idee, und die nächste Lektion sieht sie sich genau an.

Sieh es dir an

NOT IN und ein einziges NULL

Die Shopleitung ordnet das Menü der Website und fragt, welche Kategorien gar keine Produkte haben. Sie erwartet „Lebensmittel“ und „Haushalt“: Dort liegen nur Unterkategorien. Hier der erste Versuch:

SQLDatenbank: Shop
1. Warum hat NOT IN nichts geliefert statt „Lebensmittel“ und „Haushalt“?

Das ist die Falle aus der NULL-Lektion, aber jetzt kommt NULL aus der Unterabfrage und ist in der Abfrage nicht zu sehen. NOT EXISTS vergleicht keine Werte: Es fragt, ob es so ein Produkt gibt, und NULL stört dabei nicht:

SQLDatenbank: Shop

Wenn die Unterabfrage über eine Spalte läuft, die NULL sein kann, nimm NOT EXISTS oder ergänze die Unterabfrage um WHERE category_id IS NOT NULL.

Übung

Zwei Aufgaben

1. Das Qualitätsteam will die Kunden anrufen, die mindestens eine stornierte Bestellung haben.

Zeige die Namen der Kunden mit mindestens einer stornierten Bestellung.

SQLDatenbank: Shop

2. Das Marketing bereitet eine Kampagne „Schreib eine Bewertung“ für die Produkte vor, die noch niemand bewertet hat.

Zeige die Namen der Produkte ohne eine einzige Bewertung (die Tabelle reviews).

SQLDatenbank: Shop

Test

Teste dich

1. Was muss die Unterabfrage in WHERE price > (…) liefern?
2. Was prüft EXISTS (Unterabfrage)?
3. Die Unterabfrage in NOT IN (…) kann NULL liefern. Was ist sicherer?
4. Warum ist WHERE price > (SELECT AVG(price) FROM products) besser als WHERE price > 7.036?

Erstellt von Ivo Gergov im Rahmen der Kampagne von Evo Tech für zugängliche Programmierausbildung ·