Справочник по функциям

ROWS BETWEEN

Конструкция SQL

Задаёт рамку окна — строки раздела, по которым оконная функция считает значение для текущей строки.

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

Параметры

ROWS | RANGE | GROUPSключевое слово
Как считаются границы: ROWS — в строках, RANGE — по значению ORDER BY, GROUPS — в группах строк с одинаковым значением ORDER BY
Значения:ROWSRANGEGROUPS
frame_startключевое слово
Начало рамки
Значения:UNBOUNDED PRECEDINGoffset PRECEDINGCURRENT ROWoffset FOLLOWING
frame_endключевое слово
Конец рамки, не раньше её начала
Значения:offset PRECEDINGCURRENT ROWoffset FOLLOWINGUNBOUNDED FOLLOWING

Возвращаемое значение

Не возвращает значение: задаёт строки для оконной функции внутри OVER (...)

Примеры

Сумма трёх последних платежей

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

Нарастающий итог у каждого члена семьи

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

Сумма за последние 30 дней

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 и GROUPS при одинаковых ценах

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

Подробности

Границы: UNBOUNDED PRECEDING — начало раздела, offset PRECEDING — offset строк до текущей, CURRENT ROW — текущая строка, offset FOLLOWING — offset строк после текущей, UNBOUNDED FOLLOWING — конец раздела. Для RANGE offset задаётся в единицах ORDER BY, например INTERVAL '30 days' для дат.

Если рамка не указана, то с ORDER BY она идёт от начала раздела до текущей строки вместе со всеми строками с тем же значением ORDER BY (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), а без ORDER BY — весь раздел. Поэтому LAST_VALUE и NTH_VALUE без явной рамки часто возвращают не то, что ожидается.

После рамки можно исключить строки: EXCLUDE CURRENT ROW, EXCLUDE GROUP или EXCLUDE TIES. На ранжирующие функции и на LAG и LEAD рамка не влияет.

Смотрите также

Где изучить