SQL в чём разница между HAVING и WHERE

В SQL разница между **`HAVING`** и **`WHERE`** заключается в том, **когда** и **как** они фильтруют данные в запросе. ### **Основные отличия** | **Критерий** | **WHERE** | **HAVING** | |--------------------|-----------------------------------|-----------------------------------| | **Когда применяется** | **До** группировки (`GROUP BY`) | **После** группировки (`GROUP BY`) | | **Можно использовать с агрегатными функциями?** | Нет (фильтрует строки до агрегации) | Да (фильтрует результаты агрегации) | | **С какими столбцами работает?** | С любыми столбцами таблицы | Только с столбцами из `GROUP BY` или агрегатными функциями (`SUM`, `COUNT` и т. д.) | | **Производительность** | Быстрее, т. к. фильтрует данные до обработки | Медленнее, т. к. работает с уже сгруппированными данными | Агрегация — это процесс объединения множества строк в одну (или несколько) с вычислением какого-то общего значения. Агрегатные функции: COUNT() SUM() AVG() MIN() MAX() .. --- ### **Примеры** #### 1 **`WHERE` — фильтрация строк до группировки** ```sql SELECT department, COUNT(*) as employee_count FROM employees WHERE salary > 50000 -- Фильтруем ДО группировки GROUP BY department; ``` → Сначала отбираются сотрудники с зарплатой > 50k, потом считается их количество по отделам. #### 2 **`HAVING` — фильтрация после группировки** ```sql SELECT department, COUNT(*) as employee_count FROM employees GROUP BY department HAVING COUNT(*) > 5; -- Фильтруем ПОСЛЕ группировки ``` → Сначала группируем по отделам, потом оставляем только те, где больше 5 сотрудников. #### 3 **Комбинирование `WHERE` и `HAVING`** ```sql SELECT department, AVG(salary) as avg_salary FROM employees WHERE hire_date > '2020-01-01' -- Фильтруем строки ДО группировки GROUP BY department HAVING AVG(salary) > 70000; -- Фильтруем ПОСЛЕ группировки ``` → Сначала берём только сотрудников, принятых после 2020 года, затем считаем среднюю зарплату по отделам и оставляем только отделы с `avg_salary > 70000`. --- ### **Когда что использовать?** **`WHERE`** – если нужно отфильтровать **исходные строки** до любых операций (`GROUP BY`, `JOIN`, агрегация). **`HAVING`** – если нужно отфильтровать **результаты агрегации** (например, оставить только группы с `COUNT(*) > 10`). **Ошибка новичков:** ```sql -- Так нельзя! WHERE не работает с агрегатными функциями: SELECT department, COUNT(*) FROM employees WHERE COUNT(*) > 5 -- Ошибка! Такой фильтр возможен только в HAVING GROUP BY department; ``` --- ### **Вывод** - **`WHERE`** = фильтрация **до** группировки. - **`HAVING`** = фильтрация **после** группировки (работает с агрегатными функциями). - Оптимизация: сначала `WHERE` (сокращает объём данных), потом `HAVING` (фильтрует итоги).