CodeRang
Типовые задачи

Нарастающий итог SQL с SUM OVER

Нарастающий итог SQL показывает сумму от начала последовательности до текущей строки, не сворачивая исходные записи. Разберём накопительный итог SQL, кумулятивную сумму, PARTITION BY, ORDER BY и границы оконного фрейма.

Обновлено · Команда SQL Arena

Что потренируете

  • SUM() OVER с сортировкой строк
  • ROWS UNBOUNDED PRECEDING
  • Разница между ROWS и RANGE
  • PARTITION BY для независимых итогов
  • Скользящее среднее по окну

Пример задачи в тренажёре

Так выглядит задача в SQL Arena: условие, редактор, результат и схема базы.

Пред.След.Случайная
ЗаданиеОтправкиAI Mentor
Посчитайте нарастающую сумму продаж магазина

В таблице daily_sales находятся отдельные продажи магазинов. Для магазина с store_id = 1 выведите дату продажи в sale_date, сумму строки в amount и накопительную сумму в running_total. Если в один день было несколько продаж, они должны добавляться к итогу последовательно. Отсортируйте результат по дате и id продажи.

Запрос 1PostgreSQLv16
SELECT sale_date,
       amount,
       SUM(amount) OVER (
         PARTITION BY store_id
         ORDER BY sale_date, id ROWS UNBOUNDED PRECEDING
       ) AS running_total
FROM daily_sales
WHERE store_id = 1
ORDER BY sale_date, id;
Отправить
Результатstoresdaily_sales
Ответ принят

Как посчитать нарастающий итог SQL через SUM OVER

Запрос не группирует продажи по дням. Каждая строка daily_sales остаётся отдельной, поэтому две продажи 2 октября видны независимо. SUM(amount) превращается в оконную функцию благодаря OVER: агрегат больше не сокращает число строк, а вычисляет значение для каждой из них.

PARTITION BY store_id задаёт независимую последовательность для каждого магазина. В примере WHERE оставляет только store_id = 1, поэтому эффект PARTITION BY не так заметен, но в запросе сразу заложено правильное правило: если убрать фильтр, накопительный итог каждого магазина начнётся с нуля. Такой приём нужен для выручки по городам, балансов по счетам, накопленных очков игроков и других метрик внутри группы.

ORDER BY sale_date, id определяет точный порядок накопления. Одной даты недостаточно: 2 октября есть две строки. Дополнение id делает порядок однозначным. Фраза ROWS UNBOUNDED PRECEDING означает: взять все физические строки от начала окна до текущей включительно. Поэтому суммы идут 120, 200, 250, 390 и 450.

Нарастающий итог, накопительный итог и кумулятивная сумма в SQL обычно описывают один и тот же паттерн: для каждой строки считается сумма всех нужных значений до текущей позиции. SUM становится оконной функцией благодаря OVER, а ORDER BY задаёт последовательность накопления. PARTITION BY позволяет вести отдельный итог для каждой группы. Для предсказуемой построчной логики важно понимать оконный фрейм: ROWS UNBOUNDED PRECEDING означает строки от начала раздела до текущей строки. Если значения сортировки повторяются, дополнительный ключ в ORDER BY помогает определить стабильный порядок.

SQLPostgreSQL v16
SELECT sale_date,
       amount,
       SUM(amount) OVER (
         PARTITION BY store_id
         ORDER BY sale_date, id ROWS UNBOUNDED PRECEDING
       ) AS running_total
FROM daily_sales
WHERE store_id = 1
ORDER BY sale_date, id;
Результат запроса
sale_dateamountrunning_total
2026-10-01120120
2026-10-0280200
2026-10-0250250
2026-10-03140390
2026-10-0460450

Ошибки при расчёте накопительного итога SQL

01

Оставить только ORDER BY по дате

Если несколько строк имеют одинаковую дату, их внутренний порядок не определён. Для последовательного накопления лучше добавить стабильный ключ, например id. Иначе две одинаковые даты могут давать результат, который трудно интерпретировать и воспроизводить.

02

Не указать ROWS и получить поведение RANGE

В PostgreSQL окно с ORDER BY и без явной рамки по умолчанию связано с RANGE. Строки с одинаковым значением сортировки рассматриваются как peers, поэтому сумма может сразу включить все продажи одной даты. ROWS считает именно строки по очереди и подходит, когда нужен пошаговый итог.

03

Забыть PARTITION BY

Без разделения по магазину, пользователю, счёту или другой группе сумма продолжится через границу следующей сущности. Запрос синтаксически будет корректным, но бизнес-смысл результата изменится: вместо нескольких независимых итогов получится один общий.

Задачи по теме в тренажёре

Трек «Оконные функции от и до»

После базовой накопительной суммы полезно потренироваться на задачах, где окно приходится проектировать под данные. В SQL Arena есть задачи на накопительное количество игровых событий, сумму продаж по городам и историю изменения товарных остатков. Более сложные сценарии соединяют оконные суммы с разбиением событий на сессии. Для последовательной практики по этой теме есть трек «Оконные функции от и до».

Справочник по теме

Подробные статьи с синтаксисом и примерами в справочнике SQL Arena.

Частые вопросы

Как посчитать нарастающий итог SQL?

Обычно используют SUM(column) OVER с ORDER BY, определяющим порядок накопления. Для явного построчного окна можно задать ROWS UNBOUNDED PRECEDING.

Что такое накопительный итог SQL?

Это значение, которое последовательно накапливает сумму от начала выбранной последовательности до текущей строки. В отличие от GROUP BY, оконная функция позволяет сохранить исходные строки.

Как считается кумулятивная сумма SQL?

Кумулятивную сумму удобно считать через SUM() OVER (ORDER BY ...). Если итог должен начинаться заново для каждой группы, в окно добавляют PARTITION BY.

Зачем ROWS UNBOUNDED PRECEDING в нарастающем итоге?

Такой фрейм задаёт диапазон от первой строки раздела до текущей строки. Это явно описывает построчное накопление и помогает избежать неожиданной обработки строк с одинаковыми значениями сортировки.

Практика нарастающего итога в SQL

В SQL Arena можно решать задачи с накопительными суммами, скользящими окнами, ранжированием и сессиями. У каждой задачи свои таблицы, решение проверяется на скрытых данных. В PostgreSQL, MySQL, ClickHouse и BigQuery работают отдельные песочницы прямо в браузере. Бесплатно доступны 292 задачи без привязки карты, а для системной практики по этой теме можно перейти в трек «Оконные функции от и до».

Решать задачи с оконными функциями