Ответ
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; -- Фильтр по результатам агрегации
Ключевые правила:
- WHERE не может содержать агрегатные функции.
- HAVING может содержать как агрегатные функции, так и обычные колонки из
GROUP BY. - 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** — не проходит, нахуй! Группу целиком отбраковываем!
Короче, главные правила, чтобы не обосраться:
- В WHERE НЕЛЬЗЯ использовать агрегатные функции (
COUNT,SUM). Это всё равно что охраннику на проходной сказать: «Не пускай тех, у кого средняя зарплата по отделу меньше 50к». Он нихуя не знает про среднюю по отделу, он видит только Иванова И.И. с его одной зарплатой в ведомости. - HAVING — МОЖЕТ. Потому что он работает ПОСЛЕ того, как все цифры по группам уже посчитаны. Ему можно сказать: «Оставь только те отделы, где сумма продаж больше миллиона».
- Порядок, ёпта, порядок! SQL выполняет это не просто так:
- Сначала
FROM— берём таблицу. - Потом
WHERE— выкидываем ненужные строки. - Потом
GROUP BY— кучкуем оставшихся по отделам. - Потом считаем
COUNT,AVGдля каждой кучки. - И только потом
HAVING— отбрасываем целые кучки по итоговым цифрам. - Ну и в конце
SELECTиORDER BYкрасуются.
- Сначала
Так когда же тыкать HAVING? Да когда тебе нужно отфильтровать по результату вычислений, а не по исходным данным. «Заказы, где сумма позиций (SUM(price)) > 1000», «Пользователи, сделавшие больше 5 заказов (COUNT(orders))», «Отделы, где максимальная зарплата (MAX(salary)) превышает бюджет».
Вот и вся магия. Не путай охранника на входе (WHERE) с аудитором, который разгребает годовые отчёты (HAVING). И всё будет пучком, ядрёна вошь!