Встречается на 26% собеседований по PHP

В чем различие между where и having

Различие между WHERE и HAVING в SQL заключается в стадии выполнения запроса, на которой применяются эти условия, и в их предназначении: WHERE фильтрует строки до группировки, а HAVING — группы после агрегации. WHERE нельзя использовать с агрегатными функциями, тогда как HAVING специально для этого предназначен.

Как это работает

В SQL порядок выполнения запроса определяет, где применяются условия. Сначала из таблицы выбираются строки, затем к ним применяется WHERE, отбрасывая ненужные строки. После этого выполняется GROUP BY, который группирует оставшиеся строки по указанным полям. Затем для каждой группы вычисляются агрегатные функции, такие как COUNT(), SUM(), AVG(). И только после этого вступает в силу HAVING, который фильтрует уже готовые группы.

Таким образом, WHERE работает на уровне отдельных строк, а HAVING — на уровне групп. Это ключевое различие: WHERE не может ссылаться на агрегатные функции, потому что на момент его выполнения агрегация ещё не произошла. HAVING же, наоборот, предназначен для условий, которые используют результаты агрегации.

Пример

Рассмотрим таблицу сотрудники с полями имя, отдел, зарплата. Нужно получить сумму зарплат по каждому сотруднику, но только для отдела продаж, и оставить тех, у кого сумма превышает 5000.

sql
-- Шаг 1: фильтрация строк до группировки
SELECT имя, SUM(зарплата) AS сумма
FROM сотрудники
WHERE отдел = 'Продажи'
GROUP BY имя;

Здесь WHERE отбирает только строки с отделом «Продажи», затем группирует их по имени и считает сумму зарплат. Если нужно отфильтровать группы по сумме, добавляем HAVING:

sql
-- Шаг 2: фильтрация групп после агрегации
SELECT имя, SUM(зарплата) AS сумма
FROM сотрудники
GROUP BY имя
HAVING SUM(зарплата) > 5000;

В этом запросе HAVING применяется после группировки и агрегации, оставляя только те группы, где сумма зарплат больше 5000. Обратите внимание: в HAVING можно использовать агрегатную функцию SUM(), а в WHERE — нельзя.

Подводные камни

Частая ошибка — попытка использовать WHERE с агрегатной функцией, например WHERE SUM(зарплата) > 5000. Это вызовет ошибку, так как агрегация ещё не выполнена. Правильно будет перенести условие в HAVING.

Другая тонкость: HAVING можно использовать и без GROUP BY, тогда он применяется ко всей таблице как одна группа. Но на практике это редкость, и обычно HAVING идёт в паре с GROUP BY.

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

Когда использовать

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

В одном запросе можно комбинировать оба условия: WHERE отсекает лишние строки, а HAVING — лишние группы. Это позволяет строить гибкие запросы для аналитики и отчётности.

Коротко

  • WHERE фильтрует строки до GROUP BY, HAVING — группы после агрегации.
  • WHERE не работает с агрегатными функциями, HAVING — работает.
  • Порядок выполнения: FROM → WHERE → GROUP BY → HAVING → SELECT.
  • Используйте WHERE для предварительной фильтрации, HAVING — для фильтрации по результатам агрегации.
как отвечать на вопрос
пример собеседования
фреймворки на собеседовании
типичные вопросы junior
интервью вопросы и ответы