Postgresql
June 29, 2024

Оконные функции. Разница между range и rows.

Будем считать нарастающий итог salary работников в порядке даты найма. Подготовим для начала CTE для таблицы emp* таким образом.

select e.*  
from emp e
cross join generate_series(1,3,1) num
where deptno=10
Подготовленный набор данных.

Будем считать нарастающий итог 3 способами: по старинке - без явного указания окна, и с указанием в явном виде range between unbounded preceding and current row и rows between unbounded preceding and current row. Для учебных целей (наглядности) считать будем в разрезе ename.

with t as (
select e.*  
from emp e
cross join generate_series(1,3,1) num
where deptno=10
)
select t.*
, sum (sal) over (partition by ename order by hiredate) run_total_default
, sum (sal) over (partition by ename
                  order by hiredate
                  range between unbounded preceding and current row) run_total_range
, sum (sal) over (partition by ename
                  order by hiredate
                  rows between unbounded preceding and current row) run_total_rows                  
from t
order by 2

Получаем следующий результат:

Итак, поведением по умолчанию - без указания в явном виде типа кадрирования - используется range. В этом случае мы считаем агрегат по всем строкам, имеющим одинаковые значения в выражении ORDER BY, что и текущая строка. В случае кадрирования rows between unbounded preceding and current row мы считаем сумму с самой 1 строки в окне по текущую.

IRL скорее всего на промышленных данных эти суммы будут совпадать. Но нюанс стоит знать.

Проверено на PostgreSQL 15.7, compiled by Visual C++ build 1938, 64-bit

*Скрипты создания таблицы и её наполнения можно взять здесь