Расскажите об основных функциях ранжирования в 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может повторяться.