Найти N-ю по величине различную зарплату, учитывая совпадения
Таблица Employee(id, name, salary). Верните N-ю по величине различную зарплату.
Требования:
- «по величине различную» — если несколько сотрудников делят зарплату, она считается один раз
N = 2должно дать вторую различную зарплату, даже когда топ делят многие- псевдостолбец-ранг нельзя фильтровать в
WHEREтого жеSELECT— его нужно обернуть в подзапрос
SELECT salary
FROM Employee
-- ваш запрос здесь
Напишите запрос.
Ранжируйте строки через DENSE_RANK() OVER (ORDER BY salary DESC) в подзапросе, затем фильтруйте WHERE rnk = N. DENSE_RANK учитывает совпадения — равные зарплаты делят ранг, не пропуская следующий, поэтому N=2 — это вторая различная зарплата. ROW_NUMBER даёт одну строку, RANK пропускает ранги.
- ✗Использовать
ROW_NUMBER, когда совпадения должны делить ранг (нуженDENSE_RANK) - ✗Считать, что
LIMIT OFFSET Nубирает дубликаты равных зарплат - ✗Путать
RANK(пропускает ранги) иDENSE_RANK(без пропусков)
- →Чем отличаются
RANK,DENSE_RANKиROW_NUMBERна трёх людях с одной топ-зарплатой? - →Почему ранжирование должно быть в подзапросе, а не прямо в
WHERE?
Задача
Найти N-ю по величине зарплату, корректно обрабатывая совпадения.
SELECT salary
FROM (
SELECT salary,
DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
FROM Employee
) ranked
WHERE rnk = :N;
Как это работает
Оконная функция DENSE_RANK() присваивает ранг каждой строке по убыванию зарплаты. Подзапрос нужен потому, что псевдостолбец rnk нельзя использовать прямо в WHERE того же SELECT — он вычисляется позже.
Выбор функции ранжирования при совпадениях:
DENSE_RANK()— равные зарплаты делят ранг, следующий ранг не пропускается (1,1,2).N=2— вторая различная зарплата.RANK()— равные делят ранг, но следующий пропускается (1,1,3).ROW_NUMBER()— уникальный номер каждой строке (1,2,3), совпадения игнорируются.
⚠️ Для «N-й различной зарплаты» нужен именно DENSE_RANK; ROW_NUMBER даст не то при дубликатах.