Условие
Из таблиц employee(id, name, salary, dept_id) и department(id, name) выведите топ-3 сотрудников по зарплате в каждом отделе. При равенстве зарплат сотрудники с одинаковой суммой считаются разделяющими место.
Решение
Подход
Оконная функция DENSE_RANK() партиционирована по отделу и упорядочена по зарплате DESC. Все сотрудники с rank ≤ 3 попадают в топ-3. Это даёт честное «топ-3 уникальных уровней зарплаты», даже если на одном уровне несколько человек.
Реализация
WITH ranked AS (
SELECT
d.name AS dept,
e.name AS employee,
e.salary,
DENSE_RANK() OVER (
PARTITION BY e.dept_id
ORDER BY e.salary DESC
) AS rnk
FROM employee e
JOIN department d ON d.id = e.dept_id
)
SELECT dept, employee, salary
FROM ranked
WHERE rnk <= 3
ORDER BY dept, salary DESC;Подводные камни
RANKvsDENSE_RANKvsROW_NUMBER— критически разные результаты.RANKпропустит номера (1, 1, 3 — и третьего по величине нет),ROW_NUMBERоставит ровно 3 строки даже при ничьих и потеряет претендентов. На «топ-N разных уровней» братьDENSE_RANK.- Отделы с < 3 сотрудниками — попадут целиком; это правильно.
JOINс department: если у отдела нет сотрудников, его не будет в выводе. Если нужно показать пустые отделы —LEFT JOIN, начиная сdepartment.- На больших таблицах оконка по огромному отделу дорогая; индекс
(dept_id, salary DESC)ускорит.
Эталонный ответ
DENSE_RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) <= 3. RANK пропускает номера, ROW_NUMBER обрубает ничьи — в задаче «топ-N уровней» используйте именно DENSE_RANK.