📊 T-SQL Fensterfunktionen · Komplettleitfaden
1. Grundlagen: OVER() und die Funktionsweise
EINSTIEG-- Allgemeine Syntax
SELECT Spalte1, Spalte2,
Fensterfunktion() OVER ([PARTITION BY SpalteX] [ORDER BY SpalteY] [<Fensterrahmen>]) AS NeueSpalte
FROM Tabelle;
-- Einfaches Beispiel: Gesamtsumme aller Verkäufe als weitere Spalte ausgeben
SELECT
VerkaufID,
Betrag,
SUM(Betrag) OVER() AS Gesamtumsatz
FROM Verkäufe;
-- Ergebnis: Jede Zeile zeigt zusätzlich den globalen Summenwert.
2. Ranking-Funktionen: ROW_NUMBER, RANK & DENSE_RANK
RANGBILDUNG-- Vergleich ROW_NUMBER vs. RANK vs. DENSE_RANK
SELECT
Produktname,
Preis,
ROW_NUMBER() OVER (ORDER BY Preis DESC) AS Rang_ROW_NUMBER,
RANK() OVER (ORDER BY Preis DESC) AS Rang_RANK,
DENSE_RANK() OVER (ORDER BY Preis DESC) AS Rang_DENSE_RANK
FROM Produkte;
-- Top-3-Produkte pro Kategorie (ROW_NUMBER + PARTITION BY)
WITH Bewertet AS (
SELECT
Kategorie,
Produktname,
Umsatz,
ROW_NUMBER() OVER (PARTITION BY Kategorie ORDER BY Umsatz DESC) AS Rang
FROM Vertriebsdaten
)
SELECT * FROM Bewertet WHERE Rang <= 3;
3. Aggregat-Fensterfunktionen: SUM, AVG, MIN, MAX
LAUFENDE SUMMEN-- Laufende Summe der Bestellungen pro Monat (aufsteigend sortiert)
SELECT
Monat,
Umsatz,
SUM(Umsatz) OVER (ORDER BY Monat) AS Kumulierte_Umsätze
FROM Monatsumsätze;
-- Kumulierte Summe pro Kategorie (PARTITION BY + ORDER BY)
SELECT
Kategorie,
Monat,
Umsatz,
SUM(Umsatz) OVER (PARTITION BY Kategorie ORDER BY Monat) AS Kategorie_Kumuliert
FROM Vertriebsdaten
ORDER BY Kategorie, Monat;
-- Gleitender 3-Monats-Durchschnitt (mit Fensterrahmen)
SELECT
Monat,
Umsatz,
AVG(Umsatz) OVER (ORDER BY Monat
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS Gleitender_Durchschnitt
FROM Monatsumsätze;
4. Offset-Funktionen: LAG und LEAD
ZEILENVERGLEICH-- Umsatzänderung zum Vormonat
SELECT
Monat,
Umsatz,
LAG(Umsatz, 1) OVER (ORDER BY Monat) AS Vormonat,
Umsatz - LAG(Umsatz, 1) OVER (ORDER BY Monat) AS Differenz
FROM Monatsumsätze;
-- LEAD: Nächster Bestellwert innerhalb einer Bestellungs-Partition
SELECT
BestellID,
Artikel,
Menge,
LEAD(Menge) OVER (PARTITION BY BestellID ORDER BY Artikel) AS Naechste_Menge
FROM Bestelldetails;
5. FIRST_VALUE & LAST_VALUE – Erster/letzter Wert im Fenster
RAHMENREFERENZ-- Erster und letzter Umsatz pro Produkt (über alle Monate)
SELECT
ProduktID,
Monat,
Umsatz,
FIRST_VALUE(Umsatz) OVER (PARTITION BY ProduktID ORDER BY Monat) AS Erster_Umsatz,
LAST_VALUE(Umsatz) OVER (PARTITION BY ProduktID ORDER BY Monat
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS Letzter_Umsatz
FROM Vertriebsdaten;
6. Fensterrahmen: ROWS vs. RANGE
FEINTUNING-- ROWS UNBOUNDED PRECEDING: klassische laufende Summe
SELECT
Datum,
Verkauf,
SUM(Verkauf) OVER (ORDER BY Datum ROWS UNBOUNDED PRECEDING) AS Laufende_Summe
FROM Tagesverkaeufe;
-- RANGE UNBOUNDED PRECEDING inkl. gleicher ORDER-BY-Werte
SELECT
Ort,
Einwohner,
SUM(Einwohner) OVER (ORDER BY Ort RANGE UNBOUNDED PRECEDING) AS Kumuliert
FROM Staedte;
📌 Wann verwende ich welche Fensterfunktion?
/* Ranking */ Zeilen nummerieren: ROW_NUMBER() / Rang mit Lücken: RANK() / Rang ohne Lücken: DENSE_RANK() / Einteilung in Gruppen: NTILE(n)
/* Aggregat */ Laufende Summe / Durchschnitt: SUM() / AVG() mit OVER(ORDER BY ...)
/* Offset */ Vorherige Zeile: LAG() / Nächste Zeile: LEAD()
/* Wert */ Erster im Fenster: FIRST_VALUE() / Letzter im Fenster: LAST_VALUE()
/* Fensterrahmen */ ROWS UNBOUNDED PRECEDING (Start bei erster Zeile) / ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING (gleitender Dreierblock)
🚀 Performance‑Tipps
- Verwende
ROWSstattRANGE, wenn du exakte Zeilen benötigst – das vermeidet unnötigen Speicheraufwand. - Nutze eine geeignete Indexstruktur (insbesondere auf den
PARTITION BY- undORDER BY-Spalten), um Sortiervorgänge zu reduzieren. - In SQL Server 2022 kannst du mit der
WINDOW-Klausel wiederkehrende Fensterdefinitionen einmal zentral festlegen, was den Code erheblich schlanker macht. - Fensterfunktionen ersparen dir oft aufwendige Selbstverknüpfungen und korrelierte Unterabfragen – sie sind nicht nur lesbarer, sondern häufig auch schneller.
✅ Fazit: Fensterfunktionen sind eines der mächtigsten Werkzeuge in T-SQL. Mit OVER(), PARTITION BY und dem passenden Fensterrahmen löst du analytische Aufgaben elegant, wartbar und performant.