Mit Subqueries zu arbeiten ist wie Strip-Schach: Am Anfang sieht alles easy aus, bis du einen Fehler machst. Woher kommen die Fehler? Meistens aus Missverständnissen beim Syntax, Ignorieren von SQL-Logik oder einfach Unachtsamkeit. In dieser Vorlesung reden wir über die häufigsten Fehler und wie du sie vermeiden kannst.
Syntax-Fehler
Subqueries verlangen einen genauen Umgang mit dem Syntax. Vergessene Kommas, Klammern oder Aliase können deinen Query komplett crashen. Lass uns ein paar typische Probleme anschauen.
Fehlende Klammern
Klammern sind superwichtig bei Subqueries. Eine Subquery muss immer in runde Klammern, und wenn auch nur ein Paar fehlt, gibt’s einen Syntax-Fehler.
Beispiel für einen Fehler:
SELECT student_name
FROM students
WHERE student_id IN SELECT student_id FROM enrollments);
Fehlermeldung:
ERROR: syntax error at or near "SELECT"
Korrektur:
SELECT student_name
FROM students
WHERE student_id IN (SELECT student_id FROM enrollments);
Kommentar: Der Query in IN muss immer in Klammern stehen, damit SQL checkt, dass du eine Subquery ausführen willst.
Fehlende Aliase
Wenn du Subqueries im FROM-Teil benutzt, vergiss nicht, ihnen einen Alias zu geben. Ohne Alias kommt PostgreSQL komplett durcheinander.
Beispiel für einen Fehler:
SELECT student_name, avg_score
FROM (SELECT student_id, AVG(score) AS avg_score FROM grades GROUP BY student_id)
WHERE avg_score > 80;
Fehlermeldung:
ERROR: subquery in FROM must have an alias
Korrektur:
SELECT student_name, avg_score
FROM (SELECT student_id, AVG(score) AS avg_score FROM grades GROUP BY student_id) AS subquery
WHERE avg_score > 80;
Kommentar: PostgreSQL will, dass jede temporäre Tabelle (also das Ergebnis einer Subquery im FROM) einen Namen bekommt.
Performance-Probleme
Subqueries, vor allem schlecht optimierte, können deine Datenbank in eine lahme Krücke verwandeln. Die Performance leidet meistens durch zu viele Berechnungen oder fehlende Indizes.
Zu viele Berechnungen
Subqueries im SELECT-Teil werden für jede Ergebniszeile neu berechnet – das kostet richtig Zeit.
Beispiel:
SELECT student_name,
(SELECT COUNT(*) FROM enrollments WHERE enrollments.student_id = students.student_id) AS course_count
FROM students;
Wenn die Tabelle students zehntausende Zeilen hat, wird die Subquery für jede Zeile neu ausgeführt.
Optimierung:
WITH course_counts AS (
SELECT student_id, COUNT(*) AS course_count
FROM enrollments
GROUP BY student_id
)
SELECT s.student_name, c.course_count
FROM students s
LEFT JOIN course_counts c ON s.student_id = c.student_id;
CTE (Common Table Expression) oder Joins helfen dir, das ständige Neuberechnen zu vermeiden. Auf diese Technik kommen wir noch in ein paar Levels zurück :P
Fehlende Indizes
Wenn du komplexe Subqueries im WHERE-Teil nutzt, check, ob die nötigen Spalten indiziert sind.
Beispiel:
SELECT student_name
FROM students
WHERE student_id IN (SELECT student_id FROM enrollments WHERE course_id = 10);
Wenn die Spalte student_id in der Tabelle enrollments keinen Index hat, macht die Subquery einen Full Table Scan.
Optimierung: Erstelle einen Index:
CREATE INDEX idx_enrollments_course_id ON enrollments (course_id);
Du hörst ständig was von Indizes und bist bestimmt schon neugierig, was das eigentlich ist. Aber warte noch ein paar Levels. Indizes sind wichtig, aber sie sind eher ein Weg, Queries schneller zu machen, ohne den Code zu ändern. Ein schlechter Query wird dadurch nicht gut, aber auf production mit Millionen Zeilen helfen sie dir, Queries zu beschleunigen.
Logik-Fehler
Logik-Fehler in Subqueries kommen genauso oft vor wie Syntax-Fehler. Probleme entstehen oft durch falsches Verständnis von NULL, Filtern oder Aggregatfunktionen.
Falscher Umgang mit NULL
NULL ist eine Falle, die auf jeden Anfänger wartet. Wenn du IN oder NOT IN in Subqueries nutzt, kann NULL das Ergebnis beeinflussen.
Beispiel für einen Fehler:
SELECT student_name
FROM students
WHERE student_id NOT IN (SELECT student_id FROM enrollments);
Wenn es in der Tabelle enrollments Zeilen mit student_id = NULL gibt, liefert der Query gar nichts zurück. Das liegt daran, dass die Bedingung NOT IN wie NULL IS NOT IN funktioniert.
Korrektur:
SELECT student_name
FROM students
WHERE student_id NOT IN (SELECT student_id FROM enrollments WHERE student_id IS NOT NULL);
Immer NULL rausfiltern, wenn du NOT IN verwendest.
Fehler in Filterbedingungen
Oft nutzt man Subqueries für komplexe Filter, aber Fehler in den Bedingungen führen dazu, dass das Ergebnis ganz anders aussieht als erwartet.
Beispiel für einen Fehler:
SELECT student_name
FROM students
WHERE (SELECT AVG(score) FROM grades WHERE grades.student_id = students.student_id) > 80;
Wenn ein Student keine Noten hat, gibt die Subquery NULL zurück und der Student taucht nicht im Ergebnis auf.
Korrektur:
SELECT student_name
FROM students
WHERE COALESCE((SELECT AVG(score) FROM grades WHERE grades.student_id = students.student_id), 0) > 80;
Benutze COALESCE, um NULL durch Standardwerte zu ersetzen.
Tipps zur Fehlervermeidung
Damit du typische Fehler bei Subqueries vermeidest, halte dich an diese Regeln:
Korrekte Klammern und Aliase. Wenn etwas nicht läuft, check, ob alle Klammern zu sind und Aliase in Subqueries gesetzt sind.
Query-Optimierung. Versuch, Subqueries zu minimieren, wo du JOIN, WITH oder Indizes nutzen kannst.
NULL beachten. Immer dran denken, dass NULL in Subqueries auftauchen kann – nutze IS NOT NULL, COALESCE oder ähnliche Konstrukte.
Testen. Teste jede Subquery einzeln, um sicherzugehen, dass sie das gewünschte Ergebnis liefert.
Lesbarkeit. Nutze Einrückungen und Aliase, damit dein Code lesbar bleibt. Denk dran: In einem Monat weißt du selbst nicht mehr, was du da geschrieben hast.
GO TO FULL VERSION