To pytanie myli wielu skrybów: kiedy używać WHERE, a kiedy HAVING? Oba filtrują dane, ale w zupełnie innym momencie i na innym poziomie. Rozwiążmy tę zagadkę raz na zawsze.
WHERE działa na pojedynczych wierszach, zanim cokolwiek zostanie pogrupowane. Odrzuca zwoje, które nie spełniają warunku:
1SELECT kategoria_id, COUNT(*)
2FROM ksiazki
3WHERE dostepna = 1 -- najpierw odrzuć niedostępne książki
4GROUP BY kategoria_id;Tu MySQL najpierw wyrzuca wszystkie niedostępne książki, a dopiero potem grupuje i liczy te, które zostały.
HAVING działa na gotowych grupach, po obliczeniu agregatów. Odrzuca całe grupy, które nie spełniają warunku:
1SELECT kategoria_id, COUNT(*)
2FROM ksiazki
3GROUP BY kategoria_id
4HAVING COUNT(*) > 3; -- odrzuć grupy mniejsze niż 4 książki| | WHERE | HAVING | |---|-------|--------| | Kiedy działa | przed grupowaniem | po agregacji | | Na czym działa | na pojedynczych wierszach | na grupach | | Funkcje agregujące | NIE może ich użyć | MOŻE ich użyć |
Zasada kciuka: jeśli warunek dotyczy zwykłej kolumny (
dostepna = 1, rok_wydania > 2000) - użyj WHERE. Jeśli warunek dotyczy wyniku agregacji (COUNT(*) > 3, AVG(cena) > 50) - użyj HAVING.Często używamy ich razem - WHERE zawęża dane, HAVING wybiera grupy:
1SELECT kategoria_id, AVG(cena)
2FROM ksiazki
3WHERE dostepna = 1
4GROUP BY kategoria_id
5HAVING AVG(cena) > 40
6ORDER BY AVG(cena) DESC;To pełna pieśń agregacji: filtruj wiersze, grupuj, filtruj grupy, sortuj. Mistrzowski rozkaz!