Ответ
Ключевое отличие — этап выполнения запроса, на котором применяется фильтрация.
WHEREфильтрует отдельные строки таблицы ДО выполнения операций группировки (GROUP BY) или агрегации.HAVINGфильтрует уже сгруппированные результаты (агрегаты) ПОСЛЕ выполненияGROUP BY.
Сравнительная таблица:
| WHERE | HAVING | |
|---|---|---|
| Применяется к | Отдельным записям (строкам). | Группам записей, созданным GROUP BY. |
| Используется с | Любыми столбцами таблицы. | Только с агрегатными функциями (SUM, AVG, COUNT, MIN, MAX) или столбцами из GROUP BY. |
| Порядок в запросе | Выполняется до GROUP BY. |
Выполняется после GROUP BY. |
Примеры:
-
WHERE(фильтрация строк перед группировкой):-- Найти среднюю зарплату по отделам, но только для сотрудников с зарплатой > 50000 SELECT department, AVG(salary) as avg_salary FROM employees WHERE salary > 50000 -- Фильтр применяется к каждой строке ДО группировки GROUP BY department; -
HAVING(фильтрация групп после группировки):-- Найти отделы, где средняя зарплата превышает 70000 SELECT department, AVG(salary) as avg_salary FROM employees GROUP BY department HAVING AVG(salary) > 70000; -- Фильтр применяется к результату агрегации ПОСЛЕ группировки -
Комбинирование
WHEREиHAVING:-- Найти отделы (исключая 'HR'), где средняя зарплата менеджеров (job_title = 'Manager') превышает 80000 SELECT department, AVG(salary) as avg_salary FROM employees WHERE job_title = 'Manager' -- Сначала отфильтровать строки AND department != 'HR' GROUP BY department HAVING AVG(salary) > 80000; -- Затем отфильтровать сгруппированные результаты
Важно: Использовать HAVING без GROUP BY технически возможно, но это эквивалентно WHERE для агрегатных функций по всему набору данных и обычно является признаком плохого дизайна запроса.