Условие
Из таблицы employees(name, department, salary) верните максимальную зарплату для каждого отдела, где средняя зарплата по отделу превышает 5000, отсортировав результат по названию отдела в алфавитном порядке.
Решение
SELECT department,
MAX(salary) AS max_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 5000
ORDER BY department;Разбор
| Часть | Что делает |
|---|---|
GROUP BY department |
Создаёт по группе на каждый отдел |
MAX(salary) |
Самая большая зарплата в отделе |
HAVING AVG(salary) > 5000 |
Оставляет отделы со средней > 5000 |
ORDER BY department |
Сортирует по названию отдела |
Логический порядок выполнения
FROM → GROUP BY → HAVING → SELECT (агрегация) → ORDER BY
Поэтому в HAVING можно использовать агрегаты, а в WHERE — нельзя.
Можно ли в HAVING использовать колонку, которой нет в SELECT
Да: HAVING AVG(salary) > 5000 ссылается на агрегат, не выведенный в SELECT. Это валидно.
Эквивалентная запись через подзапрос
SELECT department, max_salary
FROM (
SELECT department,
MAX(salary) AS max_salary,
AVG(salary) AS avg_salary
FROM employees
GROUP BY department
) t
WHERE avg_salary > 5000
ORDER BY department;Иногда читается яснее, но чаще делает то же самое.
Подводные камни
MAX(salary)vs «сотрудник с MAX» — задача просит число, а не имя. Если бы нужен был сотрудник, нужны окноRANK()илиJOINс подзапросом.- Сотрудники с
salary = NULL— будут проигнорированы приMAX/AVG(агрегаты пропускают NULL). - Пустой отдел — если в отделе никого нет, его не будет в результате (нет строк → нет группы).
HAVING SUM(salary) > 5000— другое условие, не путать с AVG.
Эталонный ответ
SELECT department, MAX(salary)
FROM employees
GROUP BY department
HAVING AVG(salary) > 5000
ORDER BY department;