Все материалы
Продуктовая аналитикапрактикумсредний

WHERE и HAVING в SQL: разница на примерах аналитики

Понятное сравнение WHERE и HAVING в SQL: фильтрация строк до GROUP BY, фильтрация групп после агрегации и типичные ошибки аналитика.

КПКейсПрактика23 июля 2026 г.8 мин

Запрос «покажи каналы с более чем 100 заказами» выглядит почти так же, как «покажи заказы дороже 1000 ₽», но это разные уровни данных. В первом случае условие относится к группе, во втором — к строке заказа. Ошибка в выборе WHERE или HAVING даёт либо синтаксическую ошибку, либо тихо меняет смысл отчёта. Разберём вопрос на одном запросе: Где фильтровать данные: до группировки или после неё?

Когда нужен этот приём

Где фильтровать данные: до группировки или после неё?

Для выручки канала сначала оставь только оплаченные заказы за период через WHERE. После GROUP BY посчитай SUM(amount), а затем HAVING revenue > 500000. Если поставить status = paid в HAVING, читателю сложнее понять зерно, а база может сначала построить больше групп.

строка или группа?

Используй WHERE для отбора исходных строк и HAVING для отбора результатов группировки. Если условие сложно объяснить одним предложением, сначала вынеси промежуточный слой в CTE. Хороший SQL показывает не только ответ, но и уровень, на котором он получен.

Логика оператора

WHERE убирает исходные строки до GROUP BY. HAVING фильтрует уже собранные группы и может использовать агрегаты COUNT, SUM или AVG. Чем раньше отфильтрованы ненужные строки, тем меньше данных проходит дальше. Поэтому условие по исходному столбцу обычно стоит в WHERE.

Опиши результат одной фразой: «одна строка — канал за месяц». Затем раздели фильтры на две корзины: фильтры событий и фильтры агрегата. Проверь знаменатель: удаление строк WHERE меняет и числитель, и базу для последующей агрегации. Для сложных выражений используй CTE.

  • Зафиксируй одну строку результата.
  • Отдели условия по исходным строкам от условий по рассчитанным значениям.
  • Назови период, ключи связи и правило для повторов.

Рабочая версия

Названия таблиц здесь условные. При переносе сохрани зерно и бизнес-условия, а не буквальный синтаксис примера.

WHERE фильтрует заказы, HAVING — итоговые группы каналов
SELECT channel, COUNT(*) AS orders_count, SUM(amount) AS revenue
FROM orders
WHERE status = 'paid' AND paid_at >= DATE '2026-07-01'
GROUP BY channel
HAVING COUNT(*) >= 100 AND SUM(amount) >= 500000
ORDER BY revenue DESC;

Как сверить ответ

Собери пять-десять строк, где ответ можно получить вручную. Добавь NULL, дубль, объект без связанной записи и значение на границе периода. Затем сравни число строк и уникальных ключей до и после спорного шага.

Выполненный без ошибки запрос ещё не является правильным. Другой аналитик должен суметь восстановить из него источник, фильтр, grain и ожидаемое поведение на крайних случаях.

WHERE или HAVING
УсловиеУровеньОператор
status = paidисходная строкаWHERE
paid_at в периодеисходная строкаWHERE
COUNT(*) >= 100группаHAVING
SUM(amount) > 500kгруппаHAVING

Когда выбрать другой способ

HAVING без GROUP BY иногда допустим для одной общей группы, но это не делает запрос понятнее. Не переноси фильтр по дате из WHERE в HAVING. Не фильтруй SUM после округления, если порог чувствителен. И не сравнивай результаты двух запросов, если в одном WHERE исключает отмены, а в другом нет.

Используй WHERE для отбора исходных строк и HAVING для отбора результатов группировки. Если условие сложно объяснить одним предложением, сначала вынеси промежуточный слой в CTE. Хороший SQL показывает не только ответ, но и уровень, на котором он получен.

Уровни фильтрации

В условном отчёте WHERE сокращает строки, HAVING — группы.

Количество строк или групп

Небольшой эксперимент

Составь четыре запроса: товары с price > 1000, категории с COUNT(*) > 50, каналы с SUM(amount) выше порога и сегменты с AVG(order_value) ниже медианы. Для каждого подпиши, на каком уровне живёт условие. Затем сравни число обработанных строк.

  • Сначала запиши ожидаемый результат словами.
  • Проверь запрос на маленькой контрольной выборке.
  • Объясни, что запрос считает и чего не доказывает.

Следующий шаг

Используй WHERE для отбора исходных строк и HAVING для отбора результатов группировки. Если условие сложно объяснить одним предложением, сначала вынеси промежуточный слой в CTE. Хороший SQL показывает не только ответ, но и уровень, на котором он получен.

Продолжить чтение
Вся библиотека