Условие
Таблицы:
Employee(id, name, salary, departmentId)Department(id, name)
Для каждого отдела верните трёх сотрудников с топ-3 уникальных зарплат (если несколько человек получают одинаковую зарплату — все они идут в топ; топ-3 уникальных значений, не топ-3 строк).
Структура данных
Employee(id, name, salary, departmentId)
Department(id, name)
Выход: Department, Employee, Salary отсортированный по убыванию Salary внутри отдела.
Решение
DENSE_RANK() — стандартный приём
DENSE_RANK() нумерует равные значения одним рангом и не пропускает следующие — то что нужно для «топ-3 уникальных значений».
WITH ranked AS (
SELECT
d.name AS Department,
e.name AS Employee,
e.salary AS Salary,
DENSE_RANK() OVER (PARTITION BY e.departmentId ORDER BY e.salary DESC) AS rnk
FROM Employee e
JOIN Department d ON d.id = e.departmentId
)
SELECT Department, Employee, Salary
FROM ranked
WHERE rnk <= 3
ORDER BY Department, Salary DESC;Разница между RANK / DENSE_RANK / ROW_NUMBER
Зарплаты [100, 100, 80, 80, 60]:
| Функция | Ранги |
|---|---|
ROW_NUMBER |
1,2,3,4,5 |
RANK |
1,1,3,3,5 |
DENSE_RANK |
1,1,2,2,3 |
Здесь нужен DENSE_RANK ≤ 3: попадут все на ставках 100, 80, 60.
Подводные камни
RANKвместоDENSE_RANK. При двух людях с одинаковой топ-зарплатойRANKотдаст 1,1,3 — и третья позиция пропадёт (нет 2).ROW_NUMBER. Возьмёт ровно 3 строки — неверно, если двое имеют одну ставку.- Departments без сотрудников. Не появятся в выходе — это ок по задаче.
Эталонный ответ
DENSE_RANK() OVER (PARTITION BY departmentId ORDER BY salary DESC) <= 3. Не RANK, не ROW_NUMBER.