Gymterview
middle

Расскажите об основных функциях ранжирования в Transact-SQL

Ранжирующие функции возвращают порядковый номер или ранг для каждой записи внутри определённого раздела результирующего набора. Они работают через конструкцию OVER(ORDER BY ...) и не сворачивают строки, в отличие от GROUP BY.

Функция Поведение при одинаковых значениях Пример результата
ROW_NUMBER() Всегда уникальный номер 1, 2, 3, 4, 5
RANK() Одинаковый ранг + пропуск 1, 2, 2, 4, 5
DENSE_RANK() Одинаковый ранг без пропуска 1, 2, 2, 3, 4
NTILE(n) Делит на n равных групп 1, 1, 2, 2, 3

ROW_NUMBER

Присваивает уникальный последовательный номер каждой строке. При одинаковых значениях порядок распределения номеров не определён (недетерминирован).

Пример
SELECT name, marks,
       ROW_NUMBER() OVER(ORDER BY marks DESC) AS row_num
FROM ExamResult;

RANK

Присваивает ранг с учётом одинаковых значений. Если две строки имеют одинаковое значение, обе получают одинаковый ранг, а следующий ранг пропускается.

Пример
SELECT name, marks,
       RANK() OVER(ORDER BY marks DESC) AS rnk
FROM ExamResult;
-- Результат: если 2 строки имеют ранг 2, следующая получит ранг 4

DENSE_RANK

Аналогичен RANK, но без пропуска позиций. Если две строки имеют ранг 2, следующая получит ранг 3.

Пример
SELECT name, marks,
       DENSE_RANK() OVER(ORDER BY marks DESC) AS dense_rnk
FROM ExamResult;

NTILE

Делит строки на n примерно равных групп. Полезно для вычисления квартилей, децилей и других статистических разбиений.

Пример
SELECT name, marks,
       NTILE(4) OVER(ORDER BY marks DESC) AS quartile
FROM ExamResult;

Все функции ранжирования поддерживают PARTITION BY для разделения на независимые группы:

Пример
SELECT name, subject, marks,
       RANK() OVER(PARTITION BY subject ORDER BY marks DESC) AS rnk
FROM ExamResult;

На собеседовании: чётко объясните разницу между RANK и DENSE_RANK (пропуск позиций). Частая ошибка — путать ROW_NUMBER и RANK: ROW_NUMBER всегда уникален, RANK может повторяться.