SQL Academy
Premium
Funktionsreferenz

ROWS BETWEEN

SQL-Konstrukt

Legt den Fensterrahmen fest: die Zeilen der Partition, aus denen die Fensterfunktion den Wert für die aktuelle Zeile berechnet.

PostgreSQL 17.5
{ROWS | RANGE | GROUPS} BETWEEN frame_start AND frame_end

Parameter

ROWS | RANGE | GROUPSSchlüsselwort
Wie die Grenzen gezählt werden: ROWS in Zeilen, RANGE nach dem Wert in ORDER BY, GROUPS in Gruppen von Zeilen mit gleichem ORDER BY-Wert
Werte:ROWSRANGEGROUPS
frame_startSchlüsselwort
Anfang des Rahmens
Werte:UNBOUNDED PRECEDINGoffset PRECEDINGCURRENT ROWoffset FOLLOWING
frame_endSchlüsselwort
Ende des Rahmens, nicht vor seinem Anfang
Werte:offset PRECEDINGCURRENT ROWoffset FOLLOWINGUNBOUNDED FOLLOWING

Rückgabewert

Gibt keinen Wert zurück: legt die Zeilen für die Fensterfunktion in OVER (...) fest

Beispiele

Summe der letzten drei Zahlungen

PostgreSQL 17.5
SELECT payment_id,
	date,
	unit_price,
	SUM(unit_price) OVER (
		ORDER BY date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
	) AS last_three
FROM Payments
ORDER BY date;
payment_iddateunit_pricelast_three
152005-02-0388
12005-02-1220002008
62005-02-201002108
162005-03-1172107
172005-03-188115
22005-03-2321002115
182005-04-2082116
192005-05-1372115
32005-05-142035
232005-06-05300327

Laufende Summe je Familienmitglied

PostgreSQL 17.5
SELECT family_member,
	date,
	unit_price,
	SUM(unit_price) OVER (
		PARTITION BY family_member
		ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
	) AS running_total
FROM Payments
ORDER BY family_member,
	date;
family_memberdateunit_pricerunning_total
12005-02-0388
12005-02-1220002008
12005-03-1172015
12005-04-2082023
12005-05-1372030
12005-06-053002330
12006-01-151000012330
12006-03-121012340
22005-03-1888
22005-03-2321002108

Summe der letzten 30 Tage

PostgreSQL 17.5
SELECT date,
	unit_price,
	SUM(unit_price) OVER (
		ORDER BY date RANGE BETWEEN INTERVAL '30 days' PRECEDING
			AND CURRENT ROW
	) AS last_30_days
FROM Payments
ORDER BY date;
dateunit_pricelast_30_days
2005-02-0388
2005-02-1220002008
2005-02-201002108
2005-03-1172107
2005-03-188115
2005-03-2321002115
2005-04-2082108
2005-05-13715
2005-05-142035
2005-06-05300327

ROWS, RANGE und GROUPS bei gleichen Preisen

PostgreSQL 17.5
SELECT unit_price,
	COUNT(*) OVER (
		ORDER BY unit_price ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
	) AS rows_frame,
	COUNT(*) OVER (
		ORDER BY unit_price RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
	) AS range_frame,
	COUNT(*) OVER (
		ORDER BY unit_price GROUPS BETWEEN 1 PRECEDING AND CURRENT ROW
	) AS groups_frame
FROM Payments
ORDER BY unit_price;
unit_pricerows_framerange_framegroups_frame
7122
7222
8355
8455
8555
10664
16772
20882
59992
10010113

Details

Grenzen: UNBOUNDED PRECEDING ist der Anfang der Partition, offset PRECEDING liegt offset Zeilen vor der aktuellen, CURRENT ROW ist die aktuelle Zeile, offset FOLLOWING liegt offset Zeilen danach und UNBOUNDED FOLLOWING ist das Ende der Partition. Bei RANGE gibst du den Versatz in Einheiten von ORDER BY an, zum Beispiel INTERVAL '30 days' für Datumswerte.

Ist kein Rahmen angegeben, reicht er mit ORDER BY vom Anfang der Partition bis zur aktuellen Zeile samt allen Zeilen mit demselben ORDER BY-Wert (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), ohne ORDER BY ist es die ganze Partition. Deshalb liefern LAST_VALUE und NTH_VALUE ohne expliziten Rahmen oft etwas Unerwartetes.

Nach dem Rahmen kannst du Zeilen ausschließen: EXCLUDE CURRENT ROW, EXCLUDE GROUP oder EXCLUDE TIES. Auf Rangfunktionen, LAG und LEAD wirkt der Rahmen nicht.

Siehe auch

Wo du es lernst