CodeGym /Kurse /SQL SELF /Beispiele für komplexe verschachtelte Abfragen: Kombinati...

Beispiele für komplexe verschachtelte Abfragen: Kombination von EXISTS, IN, HAVING

SQL SELF
Level 14 , Lektion 3
Verfügbar

Glückwunsch, jetzt wird’s richtig spannend! Heute schauen wir uns an, wie man verschiedene Arten von Subqueries kombiniert, um knifflige Aufgaben zu lösen. EXISTS, IN, HAVING – das magische Trio, mit dem du dich wie ein Datenbank-Zauberer fühlen wirst. Wir holen Daten aus einer Tabelle, filtern sie mit Infos aus einer anderen, gruppieren und filtern dann nochmal die Gruppen. Und als Bonus: Wir checken, wie man Abfragen noch effizienter macht.

Lass uns mit einer allgemeinen Aufgabe starten, die wir Schritt für Schritt in der Vorlesung lösen werden.

Aufgabenstellung

Stell dir vor, wir haben eine Uni-Datenbank mit drei Tabellen:

Tabelle students

id name group_id
1 Otto 101
2 Maria 101
3 Alex 102
4 Anna 103

Tabelle courses

id name
1 Mathematik
2 Programmierung
3 Philosophie

Tabelle enrollments

student_id course_id grade
1 1 90
1 2 NULL
2 1 85
3 3 70

Wir sollen alle Studenten auswählen, die:

  1. Mindestens in einem Kurs eingeschrieben sind EXISTS.
  2. Mindestens in einem eingeschriebenen Kurs keine Note haben IN.
  3. Zu Gruppen gehören, deren Durchschnittsnote über 80 liegt HAVING.

Lösung mit EXISTS und IN

Schritt 1: Check, wer eingeschrieben ist (EXISTS). Wir starten mit der einfachsten Bedingung. Wir wollen wissen, welche Studenten in mindestens einem Kurs eingeschrieben sind. Dafür nehmen wir EXISTS.

SELECT name
FROM students s
WHERE EXISTS (
  SELECT 1
  FROM enrollments e
  WHERE e.student_id = s.id
);
  1. Die äußere Abfrage holt die Namen aus der Tabelle students.
  2. Im Subquery checken wir, ob es Einträge in enrollments gibt, die zum jeweiligen Studenten aus der äußeren Abfrage passen (WHERE e.student_id = s.id).
  3. SELECT 1 zeigt einfach an, dass uns nur interessiert, ob es einen Eintrag gibt, nicht was drinsteht.

Ergebnis:

name
Otto
Maria
Alex

Jetzt wissen wir, wer eingeschrieben ist. Aber wir wollen mehr. Wir wollen nach fehlenden Noten filtern.

Schritt 2: Check auf fehlende Note (IN + NULL). Jetzt filtern wir weiter: Wir brauchen nur die Studenten, die mindestens in einem Kurs keine Note haben. Hier helfen uns IN und das Wissen, wie NULL funktioniert.

SELECT name
FROM students s
WHERE id IN (
  SELECT e.student_id
  FROM enrollments e
  WHERE e.grade IS NULL
);
  1. In der äußeren Abfrage holen wir die Namen der Studenten.
  2. Das Subquery erstellt eine Liste von student_id aus enrollments, wo grade IS NULL ist.

Ergebnis:

name
Otto

Also, Otto ist der einzige Student, der einen Kurs ohne Note hat. Wie dramatisch! Aber wir sind noch nicht fertig: Wir wollen nur Gruppen berücksichtigen, deren Durchschnittsnote über 80 liegt.

Lösung mit HAVING

Schritt 3: Gruppieren und Filtern mit HAVING.

Jetzt kommt alles zusammen. Wir müssen:

  1. Den Durchschnitt für jede Gruppe berechnen.
  2. Gruppen rausfiltern, deren Durchschnittsnote über 80 liegt.
  3. Studenten aus diesen Gruppen anzeigen, die auch die vorherigen Bedingungen erfüllen.
SELECT name
FROM students s
WHERE s.group_id IN (
  SELECT group_id
  FROM students
  JOIN enrollments ON students.id = enrollments.student_id
  WHERE grade IS NOT NULL
  GROUP BY group_id
  HAVING AVG(grade) > 80
)
AND id IN (
  SELECT e.student_id
  FROM enrollments e
  WHERE e.grade IS NULL
);
  1. Die äußere Abfrage holt die Namen der Studenten, die alle Bedingungen erfüllen.
  2. Das erste Subquery im WHERE gibt eine Liste von group_id für Gruppen mit Durchschnittsnote über 80 zurück.
    • Wir joinen students mit enrollments, um an die Noten zu kommen.
    • Wir filtern nur die Einträge, wo grade IS NOT NULL ist.
    • Wir gruppieren nach group_id.
    • Mit HAVING filtern wir die Gruppen.
  3. Das zweite Subquery im WHERE prüft, ob der Student mindestens einen Kurs ohne Note hat.
  4. Beide Bedingungen werden mit AND kombiniert.

Ergebnis:

name
Otto

Wir haben also rausgefunden, dass Otto nicht nur der einzige Student ohne Note ist, sondern auch zu einer Gruppe gehört, die richtig erfolgreich ist.

Vergleich der Ansätze: EXISTS vs IN

EXISTS ist am besten, wenn du einfach nur schnell checken willst, ob es einen Eintrag gibt. Es ist effizient, weil es sofort aufhört zu suchen, sobald es den ersten Treffer findet. Das ist besonders bei großen Tabellen wichtig.

Gleichzeitig ist IN praktisch, wenn du dich auf die Inhalte konzentrierst. Zum Beispiel, wenn du eine Liste von IDs für weitere Filter brauchst. Aber denk dran: IN kann langsam werden, wenn das Subquery viele Werte zurückgibt.

Wann HAVING verwenden?

Für aggregierte Daten, bei denen du nach dem Gruppieren filtern willst, ist HAVING die beste Wahl. Aber wenn du die Bedingung in WHERE verschieben kannst (z.B. Filter auf eine Spalte), wird die Abfrage einfacher und schneller.

Komplettes Beispiel

Zur Übung noch ein Beispiel: Wähle Gruppen aus, in denen mindestens ein Student eine Note unter 75 hat, aber niemand im Kurs "Philosophie" eingeschrieben ist.

Nochmal unsere Tabellen:

Tabelle students

id name group_id
1 Otto 101
2 Maria 101
3 Alex 102
4 Anna 103

Tabelle courses

id name
1 Mathematik
2 Programmierung
3 Philosophie

Tabelle enrollments

student_id course_id grade
1 1 90
1 2 NULL
2 1 85
3 3 70
SELECT DISTINCT group_id
FROM students s
WHERE group_id IN (
  SELECT s.group_id
  FROM students s
  JOIN enrollments e ON s.id = e.student_id
  WHERE e.grade < 75
)
AND group_id NOT IN (
  SELECT s.group_id                                 -- verschachtelte Abfrage 1. Ebene
  FROM students s
  JOIN enrollments e ON s.id = e.student_id
  WHERE e.course_id = (
    SELECT id FROM courses WHERE name = 'Philosophie' -- verschachtelte Abfrage 2. Ebene :P
  )
);
  1. Das erste Subquery wählt Gruppen, in denen es Studenten mit einer Note unter 75 gibt.
  2. Das zweite Subquery schließt Gruppen aus, die mit dem Kurs "Philosophie" verbunden sind.
  3. Wir kombinieren die Bedingungen mit IN und NOT IN, um das Endergebnis zu bekommen.

Ergebnis:

group_id
101

Wie nützlich ist das?

Im echten Leben retten dich solche Ansätze, wenn du komplexe Datenbeziehungen analysieren musst. Zum Beispiel:

  • In der Analyse, um "besondere" Kundengruppen zu finden (VIP, Problemfälle usw.).
  • In Empfehlungssystemen, wo du User nach vielen Kriterien filterst.
  • Im Bewerbungsgespräch, wenn du eine komplexe SQL-Abfrage optimieren sollst.

Üben, üben, üben! So wirst du zum SQL-Profi.

Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION