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` (фильтрует итоги).