← К оглавлению занятия

Занятие 18. Фильтрация агрегированных данных. HAVING

📁 Блок: SQL / MySQL / Агрегация ⏱️ Время изучения: ~75 мин 🎯 Сложность: Средняя
#where #having #and #or #count #sum #avg #min #max

⚡ Кратко: суть темы

HAVING фильтрует группы после агрегации, WHERE — строки до неё.

  • WHERE не умеет использовать агрегатные функции.
  • HAVING идёт после GROUP BY и задаёт условия на агрегаты.
  • Порядок выполнения: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT.

Частая ошибка: использовать WHERE вместо HAVING для фильтрации по COUNT/SUM.

📖 WHERE vs HAVING

Фильтрация — отбор строк или групп по условию. В SQL для этого есть два оператора, которые работают на разных этапах:

ОператорКогда применяетсяМожет использовать агрегатыПример условия
WHERE До группировки, на этапе выборки строк Нет WHERE price > 100
HAVING После группировки и агрегации Да HAVING COUNT(*) > 2

WHERE отбрасывает строки из исходной таблицы до того, как данные будут сгруппированы. HAVING проверяет уже готовые группы и оставляет только те, которые подходят под условие.

📖 Синтаксис HAVING

Оператор HAVING размещается после GROUP BY и перед ORDER BY:

SELECT column1, aggregate_function(column2)
FROM table_name
WHERE row_condition
GROUP BY column1
HAVING group_condition
ORDER BY column1;
  • column1 — столбец группировки.
  • aggregate_function(column2) — агрегирующая функция, применённая к группе.
  • group_condition — условие, по которому отбираются группы.

GROUP BY может работать без HAVING, но HAVING без GROUP BY используется редко и обычно означает фильтрацию единственной группы из всех строк.

📖 Совместное использование WHERE и HAVING

Самый эффективный подход — сначала отобрать нужные строки через WHERE, а затем отфильтровать группы через HAVING. Так СУБД обработает меньше данных на этапе группировки.

-- Сначала оставляем продукты с упаковкой 'oz', затем группируем и фильтруем
SELECT standard_cost, COUNT(product_name) AS product_count
FROM products
WHERE LOWER(quantity_per_unit) LIKE '%oz%'
GROUP BY standard_cost
HAVING COUNT(product_name) > 2
ORDER BY product_count DESC;

📖 Фактический порядок выполнения SQL-запроса

СУБД выполняет операторы не в том порядке, в котором они написаны. Понимание порядка помогает правильно выбирать между WHERE и HAVING:

  1. FROM — выбор исходных таблиц.
  2. WHERE — фильтрация строк.
  3. GROUP BY — группировка отобранных строк.
  4. HAVING — фильтрация групп.
  5. SELECT — формирование списка столбцов.
  6. ORDER BY — сортировка результата.
  7. LIMIT — ограничение количества строк.

Проверить по документации: порядок выполнения может незначительно отличаться в разных СУБД, но общая логика FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT сохраняется в MySQL, PostgreSQL, SQLite и SQL Server.

✨ Современные практики

  • Максимально сужайте набор строк через WHERE до группировки — это ускоряет запрос.
  • Не используйте агрегаты в WHERE: пишите HAVING COUNT(*) > 1.
  • В HAVING можно задавать несколько условий через AND/OR.
  • Избегайте SELECT * с GROUP BY — это вызывает ошибку в строгих режимах SQL.