Оконные функции

Ранжирование: ROW_NUMBER, RANK, DENSE_RANK

Содержание курса

В прошлом уроке ORDER BY внутри OVER превращал агрегат в нарастающий итог — каждая строка «видела» всё накопленное до неё. Ранжирующие функции используют тот же механизм окна, но не суммируют и не усредняют: они присваивают каждой строке номер её позиции внутри секции.

Синтаксис ранжирующих функций: OVER (PARTITION BY … ORDER BY …)

Три функции — ROW_NUMBER(), RANK(), DENSE_RANK() — вызываются без аргументов. Всё, что нужно функции, она берёт из OVER-клауза:

ROW_NUMBER() OVER (PARTITION BY category ORDER BY total_amount DESC)

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

ORDER BY внутри OVER определяет, какая строка считается «первой» при ранжировании. Без него ранжирующие функции теряют смысл: RANK() и DENSE_RANK() видят все строки раздела равными и возвращают 1 для каждой, а ROW_NUMBER() раздаёт номера в произвольном порядке — воспроизвести его при следующем запросе не получится.

Важная деталь: ORDER BY внутри OVER никак не связан с ORDER BY в конце всего запроса. Первый управляет тем, как функция нумерует строки; второй — порядком строк в итоговом результате. Можно одновременно ранжировать по убыванию суммы и возвращать строки в алфавитном порядке по имени.

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

Один запрос может содержать несколько оконных функций с разными OVER-клаузами:

SELECT
    order_id,
    category,
    total_amount,
    ROW_NUMBER() OVER (PARTITION BY category ORDER BY total_amount DESC) AS rn,
    RANK()       OVER (PARTITION BY category ORDER BY total_amount DESC) AS rnk,
    DENSE_RANK() OVER (PARTITION BY category ORDER BY total_amount DESC) AS drnk
FROM orders;

Каждая функция обрабатывает своё окно независимо, хотя здесь все три окна одинаковы. Как именно rn, rnk и drnk различаются при одинаковых total_amount — следующий вопрос.

Начать заново?

Помощник начнёт новый диалог по этой задаче. Текущая переписка останется в истории до конца срока хранения.

О переписке

Можно приложить до трёх фото PNG, JPEG или WebP по 5 МБ.

Переписка и фото хранятся 90 дней после последнего принятого сообщения. Преподаватель получит доступ к диалогу, когда вы попросите его помочь.

Проверка решения остаётся отдельным действием.