Willkommen zur neuen SQL-Vorlesung! Heute schauen wir uns die unscheinbarsten, aber mega mächtigen Operatoren an – EXISTS und NOT EXISTS. Stell dir einen Spion vor, der keine Spuren hinterlässt, aber sofort meldet: "Ja, das Objekt existiert" oder "Nee, hier ist nix". Diese Operatoren liefern keine Daten direkt zurück, aber sie ermöglichen logisch präzise Checks in deinen Queries.
Fangen wir mit den Basics an. EXISTS ist ein Operator, der prüft, ob Datensätze existieren als Ergebnis einer Subquery. Wenn die Subquery mindestens einen Datensatz liefert, gibt EXISTS TRUE zurück, sonst FALSE.
SELECT 1
WHERE EXISTS (
SELECT *
FROM students
WHERE grade > 3.5
);
Wie du siehst, interessieren uns die eigentlichen Daten der Subquery nicht, sondern nur, ob solche Zeilen existieren. Wenn mindestens ein Datensatz das Kriterium erfüllt, gibt die Query 1 zurück.
Syntax von EXISTS
Die Syntax von EXISTS ist simpel:
SELECT spalten
FROM tabelle
WHERE EXISTS (
SELECT 1
FROM andere_tabelle
WHERE bedingung
);
Erklärung:
- Die verschachtelte Subquery in
EXISTSkann jede beliebige Query sein. - Das Ergebnis der Subquery entscheidet, ob
TRUEoderFALSEzurückkommt.
Beispiel: Gibt es Studenten mit einer Note über 4?
Stell dir die Tabelle students vor:
| id | name | grade |
|---|---|---|
| 1 | Otto | 3.2 |
| 2 | Anna | 4.7 |
| 3 | Dan | 5.0 |
| 4 | Lina | 2.9 |
Angenommen, wir wollen checken, ob es Studenten mit einer Note über 4 gibt. Wir nutzen folgende Query:
SELECT 'Es gibt Studenten mit hoher Punktzahl!'
WHERE EXISTS (
SELECT 1
FROM students
WHERE grade > 4
);
Ergebnis:
Es gibt Studenten mit hoher Punktzahl!
Warum ist EXISTS schneller als IN?
Der Hauptvorteil von EXISTS ist, dass er die Subquery sofort abbricht, sobald das erste Match gefunden wurde. Das heißt, wenn du nur checken willst, ob Daten existieren, kann EXISTS extrem effizient sein.
Stell dir vor, die Tabelle students hat Millionen von Zeilen, aber wir suchen nur ein einziges existierendes Match (grade > 4). Sobald SQL die erste passende Zeile findet, ist die Query fertig.
Verwendung von NOT EXISTS
Jetzt reden wir über NOT EXISTS. Dieser Operator ist das Gegenteil von EXISTS. Er gibt TRUE zurück, wenn die Subquery keinen einzigen Datensatz liefert.
Beispiel: Studenten ohne Noten (NULL) finden
Angenommen, in unserer Tabelle gibt es Studenten, die noch keine Noten haben:
| id | name | grade |
|---|---|---|
| 1 | Otto | NULL |
| 2 | Anna | 4.7 |
| 3 | Dan | 5.0 |
| 4 | Lina | NULL |
Wir wollen alle Studenten mit fehlenden Noten auswählen. Wir nutzen NOT EXISTS:
SELECT *
FROM students s
WHERE NOT EXISTS (
SELECT 1
FROM students
WHERE grade IS NOT NULL
AND id = s.id
);
Ergebnis:
| id | name | grade |
|---|---|---|
| 1 | Otto | NULL |
| 4 | Lina | NULL |
Vergleich von EXISTS und IN
Manchmal sieht es so aus, als würden EXISTS und IN das Gleiche machen. Auf den ersten Blick stimmt das, aber es gibt Unterschiede. Besonders wenn irgendwo ein NULL auftaucht. Dann kann sich IN komisch verhalten, während EXISTS dich rettet.
Schauen wir uns das mal an einem Beispiel an.
Tabelle courses (Kurse, die man belegen kann):
| course_id | name |
|---|---|
| 1 | Mathematik |
| 2 | Geschichte |
Und hier die Studenten:
| student_id | name |
|---|---|
| 1 | Alex Lin |
| 2 | Anna Song |
| 3 | Maria Chi |
| 4 | Dan Seth |
| 5 | Shadow Moon |
Tabelle enrollments (wer ist in welchem Kurs eingeschrieben):
| student_id | course_id |
|---|---|
| 1 | 1 |
| 2 | 2 |
| 3 | NULL |
Wir wollen die Namen der Kurse auswählen, für die sich jemand eingeschrieben hat. Klingt einfach.
Mit IN:
SELECT name
FROM courses
WHERE course_id IN (
SELECT course_id
FROM enrollments
);
Auf den ersten Blick sollte das klappen. Aber wenn in enrollments ein NULL bei courseid steht, wie bei Maria Chi, kann IN ... gar nichts zurückgeben! Denn NULL macht die Subquery "undefiniert" und SQL ist verwirrt: Vielleicht ist NULL genau die courseid, die wir suchen?
Mit EXISTS:
SELECT name
FROM courses c
WHERE EXISTS (
SELECT 1
FROM enrollments e
WHERE c.course_id = e.course_id
);
Aber EXISTS prüft: "Gibt es mindestens eine Zeile, wo course_id übereinstimmt?" – und das war's. Es stört sich nicht an NULL, denn es sucht konkrete Matches, nicht eine Werteliste.
Fazit: Wenn in der Subquery ein NULL vorkommen kann, nutze besser EXISTS, damit du keine Überraschungen erlebst.
Echte Aufgabenbeispiele
Tabelle students:
| id | name |
|---|---|
| 1 | Alex Lin |
| 2 | Anna Song |
| 3 | Maria Chi |
| 4 | Dan Seth |
| 5 | Shadow Moon |
Tabelle enrollments:
| student_id | course_id |
|---|---|
| 1 | 1 |
| 2 | 2 |
| 3 | NULL |
Beispiel 1. Studenten, die in Kursen eingeschrieben sind
Wir finden alle, die irgendwo schon aufgetaucht sind – also in einen Kurs eingeschrieben sind (auch wenn's komisch ist, wie bei Maria Chi):
SELECT name
FROM students s
WHERE EXISTS (
SELECT 1
FROM enrollments e
WHERE s.id = e.student_id
);
Ergebnis:
Alex Lin
Anna Song
Maria Chi
Wenn ein Student irgendwie in enrollments auftaucht – kommt er in die Auswahl, auch wenn sein course_id unklar ist.
Beispiel 2. Studenten ohne Kurse
Jetzt suchen wir die, die einfach nur im System existieren – aber noch nirgends eingeschrieben sind:
SELECT name
FROM students s
WHERE NOT EXISTS (
SELECT 1
FROM enrollments e
WHERE s.id = e.student_id
);
Ergebnis:
Dan Seth
Shadow Moon
Scheint so, als hätten diese beiden noch keinen passenden Kurs gefunden. Oder sie haben einfach vergessen, sich einzuschreiben :)
Beispiel 3. Auswahl von Kursen mit mehr als 5 eingeschriebenen Studenten
Tabelle courses:
| course_id | name |
|---|---|
| 1 | Mathematik |
| 2 | Geschichte |
| 3 | Biologie |
| 4 | Philosophie |
Tabelle enrollments:
| student_id | course_id |
|---|---|
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 1 |
| 6 | 1 |
| 7 | 2 |
| 8 | 2 |
| 9 | 2 |
| 10 | NULL |
Wir wollen die Kurse finden, in die sich mehr als fünf Studenten eingeschrieben haben. Hier fragt EXISTS quasi: "Gibt es für diesen Kurs mindestens eine Gruppe von Einträgen, wo mehr als fünf Studenten drin sind?"
SELECT name
FROM courses c
WHERE EXISTS (
SELECT 1
FROM enrollments e
WHERE c.course_id = e.course_id
GROUP BY e.course_id
HAVING COUNT(*) > 5
);
Ergebnis:
Mathematik
Nur für den Kurs "Mathematik" (course_id = 1) sind sechs Studenten eingeschrieben. Die anderen Kurse sind noch nicht so beliebt.
Häufige Fehler bei EXISTS und NOT EXISTS
- Falsches Verständnis der Subquery-Syntax. Prüfe immer, dass die Subquery korrekt auf die äußere Tabelle verweist.
- Vergessene
NULL-Prüfung. Auch wenn duEXISTSnutzt, musst du manchmal explizitNULLbehandeln. - Kein Index auf den Feldern der Subquery. Das kann die Ausführung der Query stark verlangsamen.
Das war's für heute! Jetzt weißt du, wie du EXISTS und NOT EXISTS nutzt, um die Existenz von Daten zu prüfen, und kennst die Unterschiede zu IN. In der nächsten Vorlesung tauchen wir tiefer in Subqueries ein und schauen uns deren Einsatz in SELECT für aggregierte Daten an.
GO TO FULL VERSION