Dies ist eine alte Version des Dokuments!
Inhaltsverzeichnis
Subqueries
Mit Subqueries kann man zum einen Queries erstellen, die mit unbekannten Werten arbeiten, wie z.B. das Ermitteln eines Mitarbeiters, dessen Gehalt über dem Durchschnittsgehalt liegt, wenn man das Durchschnittsgehalt nicht kennt:
SELECT employee_id, last_name, salary FROM employees WHERE salary > (SELECT AVG(salary) FROM employees);
Zum Anderen kann man mit Subqueries Werte finden, die in einem Datensatz vorkommen, in einem anderen aber nicht.
Beispiele:
1. NOT IN - am einfachsten zu lesen
-- Abteilungen, in denen KEIN Mitarbeiter arbeitet SELECT department_id, department_name FROM departments WHERE department_id NOT IN (SELECT department_id FROM employees WHERE department_id IS NOT NULL);
WICHTIG: Durch IS NOT NULL im Subquery wird ein einziges NULL-Ergebnis das NOT IN wirkungslos machen.
2. NOT EXISTS - sicherer und performanter bei großen Datenmengen
SELECT department_id, department_name FROM departments d WHERE NOT EXISTS (SELECT 1 FROM employees e WHERE e.department_id = d.department_id);
NOT EXISTS hat keine NULL-Probleme und ist somit oft die bevorzugte Variante.
3. MINUS - mengenbasiert
SELECT department_id FROM departments MINUS SELECT department_id FROM employees;
Liefert alle department_id-Werte, die in departments vorkommen, aber nicht in employees.
Ab Oracle 21c gibt es zudem EXCEPT als Standard-SQL-Alias für MINUS. Beide funktionieren identisch.
Außerdem ist EXCEPT der ISO-SQL Standard, der z.B. auch bei PostgreSQL benutzt wird.
Zudem gibt es noch weitere Operatoren:
| Operator | Bedeutung |
|---|---|
UNION | Alle Zeilen aus beiden Abfragen ohne Duplikate |
UNION ALL | Alle Zeilen aus beiden Abfragen mit Duplikaten |
INTERSECT | Nur Zeilen, die in beiden Abfragen vorkommen |
MINUS | Nur Zeilen der ersten Abfrage, die in der zweiten Abfrage fehlen |
EXCEPT | Nur Zeilen der ersten Abfrage, die in der zweiten Abfrage fehlen (ab Oracle 21c und ISO-SQL Standard) |
Mehr hierzu im Abschnitt Set Operatoren.
4. ANY - vergleicht mit irgendeinem Wert aus mehreren
-- Mitarbeiter, die mehr verdienen als IRGENDEINER in Abteilung 30 SELECT employee_id, last_name, salary FROM employees WHERE salary > ANY (SELECT salary FROM employees WHERE department_id = 30);
Merkhilfe:
| Operator | Äquivalent |
|---|---|
= ANY(…) | IN(…) |
> ANY(…) | > MIN(…) |
> ALL(…) | > MAX(…) |
< ANY(…) | < MAX(…) |
< ALL(…) | < MIN(…) |
