← Все уроки

SQL с нуля. Часть 10: оконные функции (ROW_NUMBER, RANK)

Часть 10 учебника SQL. Оконные функции для аналитика. ROW_NUMBER, RANK, DENSE_RANK для нумерации. LAG/LEAD для соседних значений. Когда брать вместо GROUP BY.

Урок курса «SQL с нуля» — открой бесплатной регистрацией
Ниже — план урока. Зарегистрируйся за 30 секунд, чтобы открыть полную теорию и 16 задач с автопроверкой прямо в браузере (PostgreSQL и SQLite с автопроверкой), сохранять прогресс и пройти все 10 частей бесплатно.
Шпаргалка: GROUP BY схлопывает 5 строк в 3 группы, OVER PARTITION BY сохраняет все 5 + добавляет столбец агрегата

TL;DR: Оконные функции считают значение для каждой строки, не схлопывая их в группы. ROW_NUMBER() OVER (PARTITION BY x ORDER BY y) нумерует. RANK и DENSE_RANK ранжируют с учётом ties. LAG/LEAD берут предыдущее/следующее значение. SUM() OVER (PARTITION BY...) — running total. Оконные функции — самый частый продвинутый вопрос на собесах.

В этой части:

Что разберёшь в этом уроке

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

Чем оконные функции отличаются от GROUP BY?

Шпаргалка: GROUP BY схлопывает 5 строк в 3 группы, OVER PARTITION BY сохраняет все 5 + добавляет столбец агрегата

Оконная функция: PARTITION делит данные на группы, ORDER BY сортирует, frame определяет окно для агрегата

Как работает running total — step-by-step:

Running total: как растёт cumulative sum по дням

Анимация: накопительный итог (running total) растёт по дням через оконную функцию

GROUP BY схлопывает строки в одну на группу:

Что такое ROW_NUMBER?

ROW_NUMBER() OVER (PARTITION BY x ORDER BY y) нумерует строки в каждой группе.

Чем RANK отличается от ROW_NUMBER?

Шпаргалка: ROW_NUMBER vs RANK vs DENSE_RANK side-by-side на 5 строках с тай. Один SQL даёт все три ранга.

При одинаковых значениях (ties):

ЗначениеROW_NUMBERRANKDENSE_RANK
100111
100211
9033 (skip 2)2
80443

Что такое LAG и LEAD?

Шпаргалка: LAG/LEAD на таблице выручка по месяцам — стрелки от текущей строки к предыдущей и следующей, MoM diff

LAG(col, n) OVER (... ORDER BY ts) — значение col за N строк назад. LEAD(col, n) OVER (... ORDER BY ts) — за N строк вперёд.

Какие агрегаты работают через OVER (SUM, AVG, COUNT, MAX, MIN)?

Любая агрегатная функция из GROUP BY (SUM, AVG, COUNT, MAX, MIN) работает и как оконная — просто добавь OVER (...) после вызова. Это даёт мощную возможность: посчитать «итог по группе» и оставить рядом с каждой строкой оригинальные значения (без схлопывания).

PARTITION BY: агрегат внутри каждой партиции считается один раз

Пример с цифрами. Таблица 6 заказов из RU и KZ. Хотим к каждой строке дописать total/avg/count по своей стране — но НЕ схлопывать:

Исходная таблица orders (6 строк):

idcountryamount
1RU50
2RU100
3RU150
4KZ100
5KZ300
6KZ500

Когда какой агрегат использовать?

ФункцияКогда нужнаПример
SUM(x) OVER (PARTITION BY g)Total по группе рядом с каждой строкойДоля строки от total: amount * 1.0 / SUM(amount) OVER (PARTITION BY country)
AVG(x) OVER (PARTITION BY g)Средний чек группыСравнить заказ с average: amount - AVG(amount) OVER (PARTITION BY country)
COUNT(*) OVER (PARTITION BY g)Сколько у user всего заказовПоказать всем строкам: COUNT(*) OVER (PARTITION BY user_id)
MAX(x) OVER (PARTITION BY g)Самый дорогой заказ юзераФлаг «это его рекорд»: amount = MAX(amount) OVER (PARTITION BY user_id)
MIN(x) OVER (PARTITION BY g)Первый заказ юзераДата первого: MIN(created_at) OVER (PARTITION BY user_id)

С ORDER BY те же 5 функций превращаются в running-варианты: running total, moving average, running count, running max/min.

Free — после регистрации
0 ₽
  • Все 10 уроков курса + 92 интерактивных задач
  • 5 SQL и 5 Python-задач в тренажёре
  • 5 кейсов · 10 метрик · 1 AI-собеседование
Начать бесплатно →
Pro
1 999 ₽/мес
  • Все 576 SQL + 561 Python-задач
  • 627 кейсов · 420 метрик · 698 заданий
  • Безлимит AI-собеседований с разбором
Оформить Pro →