Функция RANK() в SQL: синтаксис, примеры, отличие от DENSE_RANK

RANK() — оконная функция ранжирования: строки с одинаковым значением ORDER BY получают одинаковый ранг, а следующий ранг «перепрыгивает» на число совпадений. Например, для значений 100, 100, 90 ранги будут 1, 1, 3. Это ключевое отличие от DENSE_RANK (который дал бы 1, 1, 2) и от ROW_NUMBER (1, 2, 3).

Синтаксис

RANK() OVER (PARTITION BY колонки ORDER BY колонки)

Примеры использования

Пример 1: Ранг товаров по выручке внутри категории

SELECT category, product, revenue,
       RANK() OVER (PARTITION BY category ORDER BY revenue DESC) AS rnk
FROM sales;

Результат:

category | product | revenue | rnk
A        | X       | 500     | 1
A        | Y       | 500     | 1
A        | Z       | 300     | 3

Пример 2: Топ-3 по выручке с учётом ничьих

SELECT * FROM (
  SELECT product, revenue,
         RANK() OVER (ORDER BY revenue DESC) AS rnk
  FROM sales
) t
WHERE rnk <= 3;

Результат:

product | revenue | rnk
X       | 500     | 1
Y       | 500     | 1
Z       | 300     | 3
Порешать SQL-задачи в тренажёре →

Типичная ошибка

Из-за пропусков RANK может вернуть больше строк, чем ожидаешь: если два первых места, то WHERE rnk <= 3 вернёт места 1, 1, 3 — уже три строки, а 2-го места нет вовсе. Если нужен строго топ-N без пропусков — бери DENSE_RANK, а если ровно N строк — ROW_NUMBER.

Где спрашивают на собеседовании

Классический вопрос: «в чём разница RANK, DENSE_RANK и ROW_NUMBER». Разбери на примере с ничьими и объясни, какой выбрать для «топ-N по каждой группе» в зависимости от того, что делать с одинаковыми значениями.

FAQ: частые вопросы про RANK

Почему RANK пропускает номера?

Ранг отражает позицию в общем порядке: если два значения делят 1-е место, следующее логически на 3-й позиции, поэтому 2-й номер пропускается. Это поведение «спортивного» ранжирования.

Когда брать RANK, а когда DENSE_RANK?

RANK — когда важна абсолютная позиция с учётом ничьих (как в спорте). DENSE_RANK — когда нужны плотные уровни без дыр (например, «топ-3 уникальных цены»).

Можно ли ранжировать без PARTITION BY?

Да, тогда ранжирование идёт по всей выборке как по одному окну. PARTITION BY нужен, только если ранги считаются отдельно внутри каждой группы.

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

Вопросы с собеседований по теме

Смежные темы SQL

Оконные функции · Ранжирование

Другие функции SQL

ROW_NUMBER · DENSE_RANK · LAG · LEAD · NTILE · SUM OVER

Открыть SQL-тренажёр (565 задач) →