Нарастающий итог по столбцу даты скачет на равных датах — ROWS против RANGE
Нарастающий итог должен расти по одной строке, но строки с одинаковым sale_date все показывают один и тот же скачущий итог вместо пошагового роста. Объясните, почему, и исправьте.
SELECT sale_date, amount,
SUM(amount) OVER (ORDER BY sale_date) AS running_total
FROM sales;
Найдите причину и исправьте ошибку.
При ORDER BY CURRENT ROW рамки RANGE охватывает всех соседей с тем же sale_date, поэтому равная дата даёт итог по всей дате, не по строкам. Исправляют через ROWS и тайбрейкер id.
- ✗Винить дубли строк, а не семантику соседей у
RANGE - ✗Считать, что
ROWSиRANGEведут себя одинаково - ✗Добавлять
PARTITION BY sale_date, что сбрасывает итог по дате
- →Как
RANGEопределяет соседа и почему это здесь важно? - →Что гарантирует добавление уникального
idвORDER BY?
Причина — не дубли, а разница между ROWS и RANGE. У окна с ORDER BY рамка по умолчанию — RANGE ... AND CURRENT ROW, а в режиме RANGE «текущая строка» означает все строки-соседи с тем же значением sale_date. Поэтому все строки одной даты получают итог, включающий всех соседей сразу.
Переходят на ROWS (считает физические строки) и добавляют уникальный тайбрейкер, чтобы порядок был детерминированным:
SELECT sale_date, amount,
SUM(amount) OVER (ORDER BY sale_date, id
ROWS UNBOUNDED PRECEDING) AS running_total
FROM sales;
PARTITION BY sale_date не помог бы — он сбросил бы итог в начале каждой даты. DISTINCT и DESC тоже не при чём.