← Назад к вопросам
SQL: Нарастающий итог продаж по месяцам
2.0 Middle🔥 171 комментариев
#SQL и базы данных
Условие
Дана таблица продаж с полями: дата, группа товара, количество.
Нарастающим итогом рассчитайте, как увеличивалось количество проданных товаров каждый месяц каждого года с разбивкой по группе.
Требуются навыки: оконные функции, JOIN, GROUP BY.
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Нарастающий итог продаж по месяцам
Условие задачи
Рассчитать нарастающий итог (cumulative sum) количества проданных товаров по месяцам каждого года с разбивкой по группам товаров.
Основной SQL запрос
SELECT
EXTRACT(YEAR FROM sale_date) AS year,
EXTRACT(MONTH FROM sale_date) AS month,
group_name,
SUM(quantity) AS monthly_quantity,
SUM(SUM(quantity)) OVER (
PARTITION BY EXTRACT(YEAR FROM sale_date), group_name
ORDER BY EXTRACT(MONTH FROM sale_date)
) AS cumulative_quantity
FROM sales
GROUP BY
EXTRACT(YEAR FROM sale_date),
EXTRACT(MONTH FROM sale_date),
group_name
ORDER BY year, group_name, month;
Пошаговое объяснение
1. Выделение года и месяца:
EXTRACT(YEAR FROM sale_date) AS year,
EXTRACT(MONTH FROM sale_date) AS month
2. Агрегирование по месяцам и группам:
GROUP BY EXTRACT(YEAR FROM sale_date), EXTRACT(MONTH FROM sale_date), group_name
Это дает нам сумму количества за каждый месяц для каждой группы товара.
3. Оконная функция для нарастающего итога:
SUM(SUM(quantity)) OVER (
PARTITION BY EXTRACT(YEAR FROM sale_date), group_name
ORDER BY EXTRACT(MONTH FROM sale_date)
) AS cumulative_quantity
PARTITION BYразделяет данные по годам и группам (для каждой группы в каждом году свой отсчет)ORDER BY MONTHопределяет порядок накопленияSUM() OVERвычисляет нарастающую сумму
Альтернативный вариант с CTE
WITH monthly_sales AS (
SELECT
EXTRACT(YEAR FROM sale_date) AS year,
EXTRACT(MONTH FROM sale_date) AS month,
group_name,
SUM(quantity) AS monthly_qty
FROM sales
GROUP BY year, month, group_name
)
SELECT
year,
month,
group_name,
monthly_qty,
SUM(monthly_qty) OVER (
PARTITION BY year, group_name
ORDER BY month
) AS cumulative_qty
FROM monthly_sales
ORDER BY year, group_name, month;
Преимущества CTE:
- Код более читаемый
- Проще дебажить промежуточные результаты
- Лучше для сложных запросов
Пример результата
| year | month | group_name | monthly_qty | cumulative_qty |
|---|---|---|---|---|
| 2023 | 1 | Электроника | 100 | 100 |
| 2023 | 2 | Электроника | 150 | 250 |
| 2023 | 3 | Электроника | 120 | 370 |
| 2023 | 1 | Одежда | 200 | 200 |
| 2023 | 2 | Одежда | 180 | 380 |
| 2024 | 1 | Электроника | 130 | 130 |
Ключевые навыки
- EXTRACT() — выделение компонентов даты
- GROUP BY — группировка по нескольким полям
- SUM(SUM()) — агрегирование результата агрегирования
- Window Function (OVER) — вычисление по упорядоченным строкам
- PARTITION BY — логическое разделение данных
- ORDER BY в OVER — направление накопления
Оптимизация
Для больших объемов данных:
CREATE INDEX idx_sales_date_group ON sales(sale_date, group_name);
Это значительно ускорит GROUP BY и PARTITION BY операции.