В SQL: когда использовать HAVING вместо WHERE?

Ответ

HAVING используется для фильтрации результатов после применения агрегатных функций (COUNT, SUM, AVG, MAX, MIN) и группировки (GROUP BY). WHERE фильтрует отдельные строки до группировки и агрегации.

Синтаксический порядок:

SELECT column1, AGGREGATE_FUNCTION(column2)
FROM table
WHERE condition_on_rows    -- Фильтрация строк ДО группировки
GROUP BY column1
HAVING condition_on_group  -- Фильтрация групп ПОСЛЕ агрегации

Пример: Найти отделы с более чем 5 сотрудниками и средней зарплатой выше 50000.

SELECT 
    department_id, 
    COUNT(*) AS employee_count,
    AVG(salary) AS avg_salary
FROM employees
WHERE active = TRUE  -- Учитываем только активных сотрудников (фильтр строк)
GROUP BY department_id
HAVING 
    COUNT(*) > 5 
    AND AVG(salary) > 50000;  -- Фильтр по результатам агрегации

Ключевые правила:

  1. WHERE не может содержать агрегатные функции.
  2. HAVING может содержать как агрегатные функции, так и обычные колонки из GROUP BY.
  3. HAVING применяется после GROUP BY, WHERE — до.

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

  • Нужно отфильтровать итоговые группы по результату вычислений (например, "отделы, где сумма продаж > 1M").
  • Условие включает агрегатную функцию (SUM(amount) > 1000).

Ответ 18+ 🔞

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

Представь себе, что ты — начальник цеха, а данные в таблице — это рабочие, детали и прочая хуйня.

WHERE — это ты стоишь у входа на завод и отсеиваешь мудаков ДО того, как они зашли внутрь и начали работать. — Ты, Васек, пьяный — нахуй отсюда, в WHERE тебе active = FALSE. — Ты, МарьИванна, из отдела снабжения — тебе тут не надо, в WHERE тебе department != 'sales'.

То есть, WHERE фильтрует отдельные строчки из таблицы, ПРЕЖДЕ чем мы начнём что-то считать и группировать. Он нихуя не знает про «среднюю зарплату по отделу» или «количество работяг». Он видит каждого человека по отдельности и решает: этого пускать дальше, а этого — нет.

А теперь все, кого пропустили, заходят в цех. Начинается работа, группировка (GROUP BY department). Мы посчитали, сколько в каждом отделе народу и какую они в среднем лавеху получают.

И вот тут выходит HAVING — это уже главный бухгалтер или директор, который смотрит на итоговые отчёты по отделам и говорит: — Отдел маркетинга? Семь человек, средняя зп 120к? Ну пиздато, проходите, выгодные вы нам. — А вот этот отдел, блядь, «Экспериментальной ковки»... Два человека, средняя зп 25к? *HAVING COUNT() > 5 AND AVG(salary) > 50000** — не проходит, нахуй! Группу целиком отбраковываем!

Короче, главные правила, чтобы не обосраться:

  1. В WHERE НЕЛЬЗЯ использовать агрегатные функции (COUNT, SUM). Это всё равно что охраннику на проходной сказать: «Не пускай тех, у кого средняя зарплата по отделу меньше 50к». Он нихуя не знает про среднюю по отделу, он видит только Иванова И.И. с его одной зарплатой в ведомости.
  2. HAVING — МОЖЕТ. Потому что он работает ПОСЛЕ того, как все цифры по группам уже посчитаны. Ему можно сказать: «Оставь только те отделы, где сумма продаж больше миллиона».
  3. Порядок, ёпта, порядок! SQL выполняет это не просто так:
    • Сначала FROM — берём таблицу.
    • Потом WHERE — выкидываем ненужные строки.
    • Потом GROUP BY — кучкуем оставшихся по отделам.
    • Потом считаем COUNT, AVG для каждой кучки.
    • И только потом HAVING — отбрасываем целые кучки по итоговым цифрам.
    • Ну и в конце SELECT и ORDER BY красуются.

Так когда же тыкать HAVING? Да когда тебе нужно отфильтровать по результату вычислений, а не по исходным данным. «Заказы, где сумма позиций (SUM(price)) > 1000», «Пользователи, сделавшие больше 5 заказов (COUNT(orders))», «Отделы, где максимальная зарплата (MAX(salary)) превышает бюджет».

Вот и вся магия. Не путай охранника на входе (WHERE) с аудитором, который разгребает годовые отчёты (HAVING). И всё будет пучком, ядрёна вошь!