Різниця в моменті, коли вони спрацьовують:
WHEREфільтрує рядки до групування. Агрегатів у ньому ще немає.HAVINGфільтрує групи післяGROUP BYі може використовувати агрегати.
SELECT user_id, COUNT(*) AS orders, SUM(total) AS spent
FROM orders
WHERE status = 'paid' -- лише оплачені замовлення
GROUP BY user_id
HAVING SUM(total) > 10000; -- лише ті, хто витратив понад 10 000
Порядок виконання запиту: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT. Звідси й правило: умову на звичайну колонку ставлять у WHERE, бо так база відкидає зайві рядки раніше й групує менше даних.
Типові помилки:
WHERE COUNT(*) > 5- помилка: на етапіWHEREгруп ще немає.HAVING status = 'paid'безstatusуGROUP BY- помилка і в PostgreSQL, і в MySQL з режимомONLY_FULL_GROUP_BY(він увімкнений за замовчуванням). А навіть там, де такий запит проходить, він фільтрує пізніше, ніж міг би.- Посилання в
WHEREна псевдонім зSELECT(WHERE spent > 100) не працює саме через порядок виконання.