WHERE filtruje wiersze przed wykonaniem grupowania i agregacji, a zatem określa, jakie rekordy trafią do grupowania/agregacji. HAVING filtruje grupy już po zastosowaniu funkcji agregujących.
Przykład:
-- Uzyskać departamenty z sumą wynagrodzeń większą niż 50000, z wyłączeniem zwolnionych pracowników SELECT department, SUM(salary) as total FROM employees WHERE status = 'active' GROUP BY department HAVING SUM(salary) > 50000;
Tutaj:
Czy można używać funkcji agregujących w WHERE?
Błąd: próbują napisać WHERE SUM(amount) > 100, ale tak nie można — funkcje agregujące są stosowane TYLKO w HAVING.
Przykład (NIEpoprawnie):
SELECT customer_id, SUM(amount) FROM orders WHERE SUM(amount) > 100 GROUP BY customer_id -- BŁĄD: nieprawidłowe użycie SUM() w WHERE
Poprawnie:
SELECT customer_id, SUM(amount) FROM orders GROUP BY customer_id HAVING SUM(amount) > 100;
Historia
Rozwój CRM. Próba filtrowania klientów z liczbą zamówień >5 przez WHERE COUNT(order_id) > 5. Zapytanie nie działało. W rezultacie: liczba klientów w raporcie była niepoprawna, ponieważ COUNT nie można używać w WHERE.
Historia
Analiza biznesowa. Zamiast filtrowania nieaktywnych produktów w WHERE używali HAVING. Wynik: agregowanie "pustych" grup i wolny SQL. Naprawiono przenosząc filtr statusu do WHERE.
Historia
Skomplikowany raport. Użyto HAVING bez GROUP BY do filtrowania pojedynczych wierszy. W niektórych DBMS powoduje to błąd, w innych — nieoczywiste zachowanie. Wniosek: HAVING powinien występować po grupowaniu i dla warunków agregacyjnych.