Условие
Дана таблица employees(emp_id, name, salary, dept_id, manager_id). Напишите 5 SQL-запросов:
- Сотрудники, получающие зарплату больше своего непосредственного руководителя.
- Сотрудники, получающие максимальную зарплату в своём отделе.
- Список
dept_id, в которых ≤ 3 сотрудников. - Сотрудники без руководителя в своём же отделе.
- Топ отделов по суммарной зарплате (с максимальной суммой).
Решение
Подход
Каждый пункт — типичный паттерн: self-join (1, 4), оконка MAX() или подзапрос (2), HAVING COUNT (3), ORDER BY SUM DESC LIMIT 1 или RANK() (5).
Реализация
-- 1) Сотрудники, получающие больше своего руководителя
SELECT e.name, e.salary
FROM employees e
JOIN employees m ON m.emp_id = e.manager_id
WHERE e.salary > m.salary;
-- 2) Сотрудники с максимальной зп в своём отделе
SELECT name, salary, dept_id
FROM (
SELECT name, salary, dept_id,
RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS rnk
FROM employees
) t
WHERE rnk = 1;
-- 3) Отделы, где не более 3 сотрудников
SELECT dept_id
FROM employees
GROUP BY dept_id
HAVING COUNT(*) <= 3;
-- 4) Сотрудники без руководителя в своём же отделе
SELECT e.*
FROM employees e
LEFT JOIN employees m
ON m.emp_id = e.manager_id AND m.dept_id = e.dept_id
WHERE m.emp_id IS NULL;
-- 5) Отделы с максимальной суммой зарплат (могут быть ничьи)
WITH s AS (
SELECT dept_id, SUM(salary) AS total
FROM employees
GROUP BY dept_id
)
SELECT dept_id
FROM s
WHERE total = (SELECT MAX(total) FROM s);Подводные камни
- В пункте 4
LEFT JOINобязателен — если использоватьNOT EXISTS, нужно условие на тот жеdept_id. У сотрудника безmanager_idруководителя нет вовсе, и он попадёт в результат — это корректно. - В пункте 2 при равенствах
RANK()вернёт всех с максимумом;ROW_NUMBERоставит лишь одного — уточните у заказчика. - В пункте 5 одной строкой
LIMIT 1ничьи теряются.
Эталонный ответ
5 запросов выше; ключевые приёмы — self-join, оконные функции, HAVING, подзапрос на максимум.