Три самых высокооплачиваемых сотрудника в каждом отделе
Таблица employees(id, department_id, name, salary). Для каждого отдела верните трёх самых высокооплачиваемых сотрудников. Если несколько сотрудников делят третью зарплату, вернуть все такие строки допустимо.
-- топ-3 зарплаты по department_id
Напишите запрос.
Ранжируют внутри отдела оконной функцией, затем фильтруют. Помещают ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) в подзапрос и оставляют строки, где номер <= 3. Берут RANK(), чтобы сохранить всех с третьей зарплатой.
- ✗Брать глобальный LIMIT 3, дающий три строки всего, а не на отдел
- ✗Пытаться достать ранги 1-3 повторными агрегатами MAX
- ✗Путать RANK и ROW_NUMBER, когда третья зарплата делится
- →Чем RANK, DENSE_RANK и ROW_NUMBER различаются на равных зарплатах?
- →Как написать это без оконных функций, коррелированным подзапросом?
Rank the rows inside each department, then keep the top three in an outer query.
WITH ranked AS (
SELECT id, department_id, name, salary,
ROW_NUMBER() OVER (PARTITION BY department_id
ORDER BY salary DESC) AS rn
FROM employees
)
SELECT department_id, name, salary
FROM ranked
WHERE rn <= 3
ORDER BY department_id, salary DESC;
PARTITION BY department_id restarts the numbering for each department, and ORDER BY salary DESC puts the highest earner at rank 1. A global ORDER BY salary DESC LIMIT 3 would return only three people overall. If ties at the third salary must all be kept, use RANK() instead of ROW_NUMBER() — RANK() gives tied rows the same number, so rn <= 3 keeps them all.