← CS Lab Databases & Data Modeling / SQL Window Functions Open standalone ↗

A window function computes across a set of rows but keeps every row intact. Where GROUP BY folds many rows into one summary, a window function returns 7 rows for 7 rows — each gaining a value computed over a "window" of its neighbours.

Where you meet it

What it does

It attaches a per-row result that "looks around" at related rows. You still see the detail — name, salary, date — plus an extra column: its rank, its running sum, the value one row back. The original rows are never collapsed.

A window function adds a column without ever collapsing a row — which is also why you can't filter on its result in WHERE.

How it works

The magic is the OVER (...) clause. PARTITION BY splits the table into independent groups; ORDER BY orders the rows inside each group; the function then runs per group. Drop PARTITION BY and the whole table is one window.

SELECT name, dept, salary,
       RANK()       OVER (PARTITION BY dept ORDER BY salary DESC) AS rnk,
       SUM(salary)  OVER (PARTITION BY dept ORDER BY salary DESC) AS running,
       LAG(salary)  OVER (PARTITION BY dept ORDER BY salary DESC) AS prev
FROM emp;

Within each dept, rows are sorted by salary. RANK gives ties the same number then skips (1, 2, 2, 4); ROW_NUMBER would force 1, 2, 3, 4. SUM ... OVER (ORDER BY ...) accumulates top-down into a running total. LAG reaches back to the previous row's salary — NULL at the top, since there is nothing before it.

Watch out

  • Not allowed in WHERE. Window functions run after WHERE/GROUP BY/HAVING, so you cannot filter on rnk <= 3 directly — wrap the query in a subquery or CTE, then filter the outer result.
  • Frame default is RANGE, not ROWS. With an ORDER BY and ties, the default RANGE frame includes all peer rows with the same sort value — a running SUM can jump by a whole tie group at once. Use ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW for a strict row-by-row total.
  • ORDER BY inside OVER orders the window; it is independent of the query's final ORDER BY, which sorts the output.

Go deeper

Eine Window-Funktion rechnet über eine Menge von Zeilen, lässt aber jede Zeile bestehen. Wo GROUP BY viele Zeilen zu einer Zusammenfassung faltet, gibt eine Window-Funktion 7 Zeilen für 7 Zeilen zurück — jede mit einem Wert, berechnet über ein "Fenster" ihrer Nachbarn.

Wo es vorkommt

Was es tut

Sie hängt jeder Zeile ein Ergebnis an, das sich bei verwandten Zeilen "umschaut". Die Detailzeile bleibt — Name, Gehalt, Datum — plus eine Zusatzspalte: ihr Rang, ihre laufende Summe, der Wert eine Zeile zurück. Die Originalzeilen werden nie kollabiert.

Eine Window-Funktion fügt eine Spalte hinzu, ohne je eine Zeile zu kollabieren — genau darum kannst du ihr Ergebnis nicht im WHERE filtern.

Wie es funktioniert

Der Kern ist die OVER (...)-Klausel. PARTITION BY teilt die Tabelle in unabhängige Gruppen; ORDER BY ordnet die Zeilen innerhalb jeder Gruppe; die Funktion läuft dann pro Gruppe. Ohne PARTITION BY ist die ganze Tabelle ein Fenster.

SELECT name, dept, salary,
       RANK()       OVER (PARTITION BY dept ORDER BY salary DESC) AS rnk,
       SUM(salary)  OVER (PARTITION BY dept ORDER BY salary DESC) AS running,
       LAG(salary)  OVER (PARTITION BY dept ORDER BY salary DESC) AS prev
FROM emp;

Je dept werden die Zeilen nach Gehalt sortiert. RANK gibt Gleichstand dieselbe Zahl und springt dann (1, 2, 2, 4); ROW_NUMBER würde 1, 2, 3, 4 erzwingen. SUM ... OVER (ORDER BY ...) summiert von oben nach unten zur laufenden Summe. LAG greift auf das Gehalt der vorherigen Zeile zurück — ganz oben NULL, weil davor nichts liegt.

Worauf achten

  • Nicht im WHERE nutzbar. Window-Funktionen laufen nach WHERE/GROUP BY/HAVING, du kannst also nicht direkt auf rnk <= 3 filtern — pack die Query in eine Subquery oder CTE und filtere das äußere Ergebnis.
  • Frame-Default ist RANGE, nicht ROWS. Mit ORDER BY und Gleichstand umfasst der Default-RANGE-Frame alle Peer-Zeilen mit demselben Sortierwert — eine laufende SUM kann um eine ganze Gleichstand-Gruppe auf einmal springen. Für eine strikt zeilenweise Summe ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW nutzen.
  • ORDER BY innerhalb von OVER ordnet das Fenster; es ist unabhängig vom finalen ORDER BY der Query, das die Ausgabe sortiert.

Mehr dazu

Next up
Databases & Data ModelingSQL Subqueries & CTEs Databases & Data ModelingSQL Transactions & ACID All concepts →