JavaRush /Курсы /SQL SELF /Сравнение оконных функций с агрегатными функциями:

Сравнение оконных функций с агрегатными функциями: GROUP BY vs PARTITION BY

SQL SELF
30 уровень , 0 лекция
Открыта

На первый взгляд, оконные функции и агрегатные функции кажутся схожими инструментами для анализа и обработки данных. Ведь и те, и другие выполняют вычисления, такие как сумма, среднее, ранжирование и т. д. Но разберёмся, чем они отличаются по сути.

Агрегатные функции (GROUP BY)

Агрегатные функции работают следующим образом:

  • Они группируют строки по указанным столбцам.
  • После группировки каждая группа превращается в одну строку результата.
  • Пример: вы хотите узнать суммарный доход по каждому региону.
SELECT region, SUM(sales) AS total_sales
FROM sales_data
GROUP BY region;

Особенность: GROUP BY "сжимает" данные. Если вы используете группировку, то все строки, входящие в одну группу, исчезают — остаётся только результат агрегации.

Оконные функции (PARTITION BY)

Оконные функции, напротив:

  • Соблюдают изначальную структуру данных (никаких сжатий или исчезновений строк!).
  • Могут выполнять вычисления внутри "окон" — логически обособленных групп строк.

Пример: вы хотите узнать долю продаж каждого города в суммарных продажах его региона, но при этом сохранить все данные.

SELECT
    region,
    city,
    sales,
    SUM(sales) OVER (PARTITION BY region) AS total_sales_by_region
FROM sales_data;

Особенность: использование оконных функций не удаляет строки, а лишь добавляет новые вычисляемые значения к каждой строке.

Пример: SUM() с GROUP BY vs SUM() с PARTITION BY

Чтобы лучше понять разницу, давайте рассмотрим, как SUM() работает в обоих случаях. Представим, что у нас есть таблица sales_data следующего вида:

region city sales
North CityA 100
North CityB 150
South CityC 200
South CityD 250

Суммирование с помощью GROUP BY

Мы хотим узнать общий объём продаж по каждому региону:

SELECT region, SUM(sales) AS total_sales
FROM sales_data
GROUP BY region;

Результат будет выглядеть так:

region total_sales
North 250
South 450

Что произошло: строки сгруппировались по region, и каждая группа была "сжата" в одну строку с суммой продаж.

Суммирование с помощью PARTITION BY

Теперь сделаем то же самое с оконной функцией:

SELECT
    region,
    city,
    sales,
    SUM(sales) OVER (PARTITION BY region) AS total_sales_by_region
FROM sales_data;

Результат:

region city sales total_sales_by_region
North CityA 100 250
North CityB 150 250
South CityC 200 450
South CityD 250 450

Что произошло: PARTITION BY не "сжал" строки. Вместо этого он выполнил расчёт суммы внутри определённых окон (каждый регион — это отдельное окно).

Когда использовать GROUP BY и когда — PARTITION BY?

GROUP BY: подходит для финальных отчётов

GROUP BY полезен, когда вы хотите сократить объём данных и получить итоговые результаты на уровне групп. Например:

  • Суммарные продажи по месяцам.
  • Подсчёт количества заказов по категориям товаров.

Пример:

SELECT category, COUNT(*) AS total_orders
FROM orders
GROUP BY category;

PARTITION BY: идеален для анализа и детализации

PARTITION BY подходит, когда вам нужно сохранить все строки данных и дополнительно вычислить что-то для каждой из них. Например:

  • Определить долю продаж каждого товара в категории.
  • Нумерация строк внутри каждой группы.

Пример расчёта доли продаж:

SELECT
    category,
    product,
    sales,
    ROUND(
        (sales * 100.0) / SUM(sales) OVER (PARTITION BY category),
        2
    ) AS sales_percentage
FROM sales_data;

Пример: использование нескольких оконных функций

Одним из преимуществ оконных функций является возможность использовать несколько вычислений сразу. Например:

SELECT
    region,
    city,
    sales,
    SUM(sales) OVER (PARTITION BY region) AS total_sales,
    RANK() OVER (PARTITION BY region ORDER BY sales DESC) AS sales_rank
FROM sales_data;

Результат:

region city sales total_sales sales_rank
North CityB 150 250 1
North CityA 100 250 2
South CityD 250 450 1
South CityC 200 450 2

Преимущества оконных функций над GROUP BY

Сохранение оригинальных данных: GROUP BY "сжимает" строки, а оконные функции позволяют сохранить оригинальную структуру таблицы.

Несколько вычислений в одном запросе: Вы можете использовать несколько оконных функций с разными параметрами PARTITION BY и ORDER BY, сохраняя данные.

Гибкость анализа: Оконные функции позволяют настроить расчёты под ваши нужды: накопительные суммы, ранжирование, долевые расчёты и многое другое.

Пример гибкости

Попробуем объединить несколько функций:

SELECT
    region,
    city,
    sales,
    SUM(sales) OVER (PARTITION BY region) AS total_sales,
    AVG(sales) OVER (PARTITION BY region) AS avg_sales,
    RANK() OVER (PARTITION BY region ORDER BY sales DESC) AS rank
FROM sales_data;

Результат:

region city sales total_sales avg_sales rank
North CityB 150 250 125.0 1
North CityA 100 250 125.0 2
South CityD 250 450 225.0 1
South CityC 200 450 225.0 2

Ограничения и типичные ошибки

Одной из распространённых ошибок является попытка использовать PARTITION BY, когда требуется "сжать" данные. Например, вместо:

SELECT region, SUM(sales) AS total_sales
FROM sales_data
GROUP BY region;

Некоторые пытаются написать так:

SELECT
    region,
    SUM(sales) OVER (PARTITION BY region) AS total_sales
FROM sales_data;

Однако это вернёт все строки, не сократив объём данных (что не всегда то, что нужно).

Теперь вы точно знаете, когда использовать GROUP BY, а когда — оконные функции. Это похоже на выбор между молотком и отверткой: оба инструмента работают с гвоздями... но по-разному.

2
Задача
SQL SELF, 30 уровень, 0 лекция
Недоступна
Сумма продаж по регионам с сохранением всех строк (`PARTITION BY`)
Сумма продаж по регионам с сохранением всех строк (`PARTITION BY`)
Комментарии (4)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Vlad Tagunkov Уровень 50
17 января 2026
Привет всем кто читает этот пост. Поздравляю тебя с достижением Экватора данного курса(ну почти). Если ты дошел до этой лекции решая почти все задачи (за исключением когда надо угодить валидатору).Ты просто избранный. Первую задачу на этом курсе решило где то 750 человек. Задачу этой лекции - 30 человек. Если ты решил эту задачу то входишь в 4% наиболее настойчивых. Надеюсь увидимся на 61 левеле этого курса. Надеюсь я не сойду с дистанции во второй половине
Евгений Уровень 49 Expert
4 сентября 2025
Хочу подсказать, если кто не знал, то вы можете добавлять возвращать все колонки исходной таблицы + дополнительные колонки вот таким образом:

SELECT *, ... AS total_sales_by_region
Или вот так:

SELECT sd.*, ... AS total_sales_by_region
FROM sales_data AS sd
Чтобы не переписывать все колонки вручную 😉
Ra Уровень 35 Student
5 августа 2025
"Молотком и отверткой: оба инструмента работают с гвоздями" 🙈🤦‍♂️🤦‍♀️
15 ноября 2025
Главное, чтобы тестовые задания не были разработаны по такому же принципу))