Ответ
Основное различие: WHERE фильтрует строки до их группировки и агрегации, а HAVING фильтрует сгруппированные данные после выполнения агрегатных функций.
Порядок выполнения запроса
Чтобы понять разницу, важно знать упрощенный порядок выполнения SQL-запроса:
FROM/JOINWHERE(фильтрация отдельных строк)GROUP BY(группировка строк)- Агрегатные функции (
SUM,COUNT, ...) HAVING(фильтрация групп)SELECTORDER BY
Ключевые отличия
-
Объект фильтрации:
WHEREработает с отдельными строками таблицы.HAVINGработает с группами строк, созданнымиGROUP BY.
-
Использование агрегатных функций:
- В
WHEREнельзя использовать агрегатные функции (SUM,COUNT,AVGи т.д.), так как на этом этапе они еще не вычислены. HAVINGпредназначен именно для фильтрации по результатам агрегатных функций.
- В
Примеры:
Представим таблицу Orders с колонками customer_id, order_date, amount.
WHERE — отфильтровать заказы до группировки
Задача: Найти общую сумму заказов для каждого клиента, но учитывать только заказы дороже 100.
SELECT
customer_id,
SUM(amount) as total_amount
FROM Orders
WHERE amount > 100 -- Сначала отбираем строки, где amount > 100
GROUP BY customer_id;
HAVING — отфильтровать результат после группировки
Задача: Найти клиентов, у которых общая сумма всех заказов превышает 1000.
SELECT
customer_id,
SUM(amount) as total_amount
FROM Orders
GROUP BY customer_id
HAVING SUM(amount) > 1000; -- Группируем, считаем SUM и только потом фильтруем группы Ответ 18+ 🔞
А, ну ты про эту вечную путаницу WHERE и HAVING? Давай разжую, как в детском саду, только с матом, чтобы лучше запомнилось.
Представь себе, что ты на заводе по сборке хуёв с винтом. Вот у тебя конвейер, на котором едут заготовки — это твои строки из таблицы.
WHERE — это такой охранник-садист на входе. Каждую заготовку он проверяет по одному: «Ты, сука, больше 100 грамм весишь? Нет? Нахуй отсюда, в брак!» И только те, кто прошел, едут дальше на группировку. Он работает ДО того, как ты что-то посчитал или сгруппировал. В WHERE нельзя сказать «пропусти тех, у кого суммарный вес больше кило» — потому что сумм ещё нет, ты на каждую деталь по отдельности смотришь.
SELECT
customer_id,
SUM(amount) as total_amount
FROM Orders
WHERE amount > 100 -- Охранник отсеивает каждый мелкий заказ по отдельности
GROUP BY customer_id;
А теперь детали проехали и попали в цех GROUP BY. Тут их сваливают в кучки по customer_id и начинают клепать: «Так, для Васечка — вот эти пять болванок, скручиваем, получаем общий вес».
HAVING — это уже начальник цеха, жирный мудак с сигарой. Он подходит к готовым, собранным хуям (то есть к группам) и говорит: «Что это за херня? Общий вес меньше 1000 грамм? Нахуй всю эту кучку в утиль, клиент — нищеброд!» Он фильтрует ПОСЛЕ группировки и всех вычислений. Поэтому в HAVING можно и нужно тыкать агрегатными функциями — SUM(), COUNT() — потому что они уже посчитаны.
SELECT
customer_id,
SUM(amount) as total_amount
FROM Orders
GROUP BY customer_id
HAVING SUM(amount) > 1000; -- Начальник цеха отбраковывает целые группы готовых изделий
Короче, запомни так:
-
Порядок на конвейере (пиздец как важно):
FROM— привезли сырьё.WHERE— охранник отфильтровал кривые заготовки (работает со строками).GROUP BY— сгруппировали по клиентам в цеху.- Посчитали
SUM()— сделали готовые изделия. HAVING— начальник отбраковал хилые партии (работает с группами).SELECT— упаковали в красивую коробку.ORDER BY— выстроили на складе по росту.
-
Главный признак:
- Если в условии есть слова «каждый», «отдельный» — это
WHERE. «Где каждый заказ больше ста». - Если в условии есть «общий», «суммарный», «в среднем» — это
HAVING. «Где общая сумма больше тысячи».
- Если в условии есть слова «каждый», «отдельный» — это
Вот и вся магия, ёпта. Не путай охранника с начальником цеха, а то получишь пизды и от того, и от другого.