SELECT round(avg(gehalt))
FROM mitarbeiter;
SELECT name
FROM mitarbeiter
WHERE gehalt > 67333
ORDER BY name;
Problem: Manuelle Ermittlung des Durchschnittswertes und Eintragung in die zweite Abfrage
Kombination zweier Aggregierungsstufen:
Schachtelung von Abfragen
SELECT name
FROM mitarbeiter
WHERE gehalt >= (
SELECT round(avg(gehalt))
FROM mitarbeiter
)
ORDER BY name;
SELECT name
FROM mitarbeiter
WHERE gehalt >= (
SELECT round(avg(gehalt))
FROM mitarbeiter
)
ORDER BY name;
Der Vergleichsoperator
>=
erfordert linke und rechte Seite mit kompatiblen Typ
Ist in diesem Fall gegeben:
Abfrage liefert Ergebnis mit einer Zeile und eine Spalte
Tabelle
Tabelle, eine Zeile, eine Spalte
Kann als Wert interpretiert werden
SELECT
name,
gehalt,
(SELECT round(avg(gehalt)) FROM mitarbeiter) AS dgehalt,
gehalt - (SELECT round(avg(gehalt)) FROM mitarbeiter) AS diff
FROM mitarbeiter
ORDER BY
gehalt - (SELECT round(avg(gehalt)) FROM mitarbeiter) desc;
Unterabfragen ermöglichen die Kombination von Detail- und aggregierten Werten in einer Abfrage
Mehrfach verwendete Unterabfragen herausziehen und mit with definieren
with
dg AS (SELECT round(avg(gehalt)) AS dgehalt
FROM mitarbeiter)
SELECT
name,
gehalt,
dgehalt,
gehalt - dgehalt AS diff
FROM mitarbeiter cross join dg
ORDER BY gehalt - dgehalt desc;
Jeder Mitarbeiter-Datensatz soll um den Wert "dgehalt" ergänzt werden -> cross join
Alle Mitarbeiter, die in Abteilungen arbeiten, die direkt von Meier (109) geleitet werden
SELECT oeid, name
FROM mitarbeiter
WHERE oeid IN (
SELECT oeid
FROM orgeinheit
WHERE leitung=109
);
Unterabfrage liefert:
15
17
Hinter dem Schlüsselwort IN muss eine Liste von Werten kommen
Für eine Unterabfrage bedeutet das: mehrere Zeilen aber nur eine Spalte
SELECT oeid, name
FROM mitarbeiter
WHERE oeid IN (
SELECT oe.oeid
FROM orgeinheit oe
join mitarbeiter m ON m.mid=oe.leitung
WHERE name='Meier'
);
Durchschnitt pro Orgeinheit
SELECT
oeid,
name,
(SELECT round(avg(gehalt))
FROM mitarbeiter dg
WHERE dg.oeid=m.oeid) AS dgehalt_abt
FROM mitarbeiter m
ORDER BY oeid, mid;
SELECT m.oeid, name, gehalt,
dgehalt_abt,
gehalt - dgehalt_abt AS diff
FROM mitarbeiter m
join
(SELECT oeid, round(avg(gehalt)) AS dgehalt_abt
FROM mitarbeiter
group by oeid) dabt ON m.oeid=dabt.oeid;
Kann als Ergebnis eine "echte" Tabelle abliefern
with
dabt AS (
SELECT oeid, round(avg(gehalt)) AS dgehalt_abt
FROM mitarbeiter
group by oeid)
SELECT m.oeid, name, gehalt,
dgehalt_abt,
gehalt - dgehalt_abt AS diff
FROM mitarbeiter m
join dabt ON m.oeid=dabt.oeid;
SELECT |
(SELECT …) - eine Zeile, eine Spalte |
---|---|
FROM |
(SELECT …) - keine Einschränkungen |
WHERE |
(SELECT …)
|
GROUP BY |
nicht zulässig |
HAVING |
(SELECT …) - eine Zeile, eine Spalte |
ORDER BY |
(SELECT …) - eine Zeile, eine Spalte |
Abteilungen mit größtem Durchschnittsgehalt
with
dg AS (
SELECT oeid, avg(gehalt) AS dgehalt
FROM mitarbeiter
group by oeid
)
SELECT oeid
FROM dg
WHERE dgehalt >= all (SELECT dgehalt FROM dg);
Abteilungen mit größtem Durchschnittsgehalt
with
dg AS (
SELECT oeid, avg(gehalt) AS dgehalt
FROM mitarbeiter
group by oeid
)
SELECT oeid
FROM dg dg1
WHERE not exists (
SELECT dgehalt
FROM dg dg2
WHERE dg2.dgehalt > dg1.dgehalt
);
Abteilungen mit dem nicht-kleinsten Durchschnittsgehältern
with
dg AS (
SELECT oeid, avg(gehalt) AS dgehalt
FROM mitarbeiter
group by oeid
)
SELECT oeid
FROM dg
WHERE dgehalt > some (SELECT dgehalt FROM dg);