====== 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 [[opendocks:oracle-sql-nutshell-doku:nutshell-doku-06|Set Operatoren]] auf der nächsten Seite.
===== 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(...)'' |
[[opendocks:oracle-sql-nutshell-doku:nutshell-doku-04|Zurück]] - [[opendocks:oracle-sql-nutshell-doku:nutshell-doku-06|Weiter]]