HAVING a WHERE
Filtrowanie przed grupowaniem i po nim oraz klauzula, która ma dostęp do agregatu
HAVING a WHERE to bezpłatna lekcja Coding Interview Prep na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Coding Interview Prep, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Coding Interview Prep zawiera 4 lekcji w sumie.
Pytanie, które Państwo usłyszą
„Jaka jest różnica między WHERE a HAVING?” to jedno z najczęściej zadawanych pytań na rozmowach kwalifikacyjnych dotyczących SQL. Słaba odpowiedź brzmi: „HAVING służy do funkcji agregujących”. Dobra odpowiedź wyjaśnia kiedy wykonywana jest każda klauzula w potoku zapytania.
Właśnie czas wykonania jest tu najważniejszy: WHERE filtruje wiersze przed grupowaniem, a HAVING filtruje grupy po agregacji.
Miejsce w kolejności wykonywania
Proszę przypomnieć sobie logiczną kolejność wykonywania zapytania:
FROM/JOIN→ utworzenie zbioru wierszyWHERE→ filtrowanie poszczególnych wierszyGROUP BY→ połączenie w grupyHAVING→ filtrowanie grupSELECT→ wybór kolumnORDER BY→ sortowanie
WHERE jest wykonywane, zanim grupy powstaną, a HAVING później, dlatego HAVING może korzystać z wartości agregujących, a WHERE nie.
WHERE nie widzi wartości agregujących
Ponieważ WHERE jest wykonywane przed grupowaniem, nie ma jeszcze żadnych wartości agregujących. Zapisanie WHERE COUNT(*) > 5 jest błędem składni we wszystkich standardowych bazach danych.
Rekruterzy umieszczają dokładnie ten fragment, aby sprawdzić, czy rozumieją Państwo potok wykonywania zapytania. Funkcja agregująca nie istnieje jeszcze w momencie obliczania WHERE.
-- ERROR: aggregate not allowed in WHERE
SELECT department, COUNT(*)
FROM employees
WHERE COUNT(*) > 5
GROUP BY department;HAVING filtruje grupy
Po przeniesieniu warunku dotyczącego funkcji agregującej do HAVING zapytanie działa, ponieważ HAVING jest wykonywane po utworzeniu grup i obliczeniu ich wartości agregujących.
Należy odczytać to następująco: „pogrupować pracowników, a następnie pozostawić tylko te działy, w których liczba pracowników przekracza pięciu”.
SELECT department, COUNT(*) AS headcount
FROM employees
GROUP BY department
HAVING COUNT(*) > 5;Filtry wierszy należy umieszczać w WHERE
Odwrotnym błędem jest filtrowanie surowych wierszy w HAVING. Często daje ono poprawny wynik, ale jest wolniejsze i mylące, ponieważ grupowane są wiersze, które miały zostać odrzucone.
Praktyczna zasada: filtrowanie według wartości surowej kolumny → WHERE. Filtrowanie według wartości agregującej → HAVING. Wczesne filtrowanie wierszy zmniejsza ilość danych przetwarzanych podczas grupowania.
-- Better: drop inactive rows BEFORE grouping
SELECT department, COUNT(*) AS headcount
FROM employees
WHERE status = 'active'
GROUP BY department
HAVING COUNT(*) > 5;Obie klauzule razem
Kompletne zapytanie często korzysta z obu klauzul. WHERE najpierw ogranicza liczbę wierszy, a HAVING pozostawia następnie grupy spełniające warunek. Czytanie zapytania od góry do dołu odpowiada logicznej kolejności wykonywania.
Przykład: spośród zamówień złożonych w tym roku znaleźć klientów, którzy wydali łącznie więcej niż 1000.
SELECT customer_id, SUM(amount) AS total_spent
FROM orders
WHERE order_date >= '2024-01-01'
GROUP BY customer_id
HAVING SUM(amount) > 1000;HAVING dla kolumn niezagregowanych
HAVING może odwoływać się do kolumny użytej do grupowania, a nie tylko do funkcji agregujących. HAVING department = 'Sales' jest poprawne, ale pozbawione sensu: ten filtr powinien znajdować się w WHERE, aby został wykonany wcześniej.
Jeśli rekruter pokaże HAVING filtrujące zwykłą kolumnę używaną do grupowania, oczekiwana uwaga brzmi: „dla większej wydajności należy przenieść ten warunek do WHERE”.
-- Works but inefficient; prefer WHERE department = 'Sales'
SELECT department, COUNT(*)
FROM employees
GROUP BY department
HAVING department = 'Sales';HAVING bez GROUP BY
To subtelny przypadek: HAVING jest poprawne nawet bez GROUP BY. Cała tabela staje się jedną niejawną grupą, a HAVING filtruje tę pojedynczą grupę.
Jeśli warunek dotyczący funkcji agregującej jest fałszywy, otrzymują Państwo zero wierszy; jeśli jest prawdziwy, jeden wiersz. Jest to rzadko przydatne, ale rekruterzy pytają o ten przypadek, aby sprawdzić zrozumienie pojęcia grupy niejawnej.
-- Returns the count only if the table has > 100 rows
SELECT COUNT(*) AS total
FROM orders
HAVING COUNT(*) > 100;Czy HAVING może używać aliasu z SELECT?
Podobnie jak w przypadku zakresu aliasów w innych kontekstach, różne dialekty zachowują się odmiennie. Postgres i MySQL pozwalają, aby HAVING odwoływało się do aliasu z SELECT; SQL Server i Oracle na to nie pozwalają.
Przenośna praktyka polega na powtórzeniu wyrażenia agregującego w HAVING. Działa ono w każdym silniku i pozwala uniknąć niespodzianek podczas rozmowy dotyczącej wielu baz danych.
-- Portable: repeat the aggregate, do not rely on the alias
SELECT region, SUM(amount) AS total
FROM sales
GROUP BY region
HAVING SUM(amount) > 5000;Aspekt wydajnościowy
Aby zrobić dobre wrażenie, warto połączyć te klauzule z wydajnością: WHERE zmniejsza liczbę wierszy, które silnik grupowania musi przeskanować, i może korzystać z indeksów; HAVING działa na już zagregowanych grupach, więc nie może zmniejszyć kosztu grupowania.
Najważniejszy wniosek, którego oczekują rekruterzy: każdy filtr należy stosować możliwie wcześnie. W HAVING powinny znaleźć się tylko warunki, które rzeczywiście zależą od wartości agregującej.
Odpowiedź w jednym zdaniu
Proszę zapamiętać na rozmowę kwalifikacyjną: „WHERE filtruje wiersze przed grupowaniem i nie widzi wartości agregujących; HAVING filtruje grupy po agregacji i jest jedyną klauzulą, która może sprawdzać wartość agregującą”.
Jeśli dodadzą Państwo do tego listę kolejności wykonywania, otrzymają kompletną odpowiedź brzmiącą jak odpowiedź doświadczonego specjalisty.
Szybkie sprawdzenie
Proszę zdecydować, do której klauzuli należy każdy warunek.
Podsumowanie
WHERE: filtruje wiersze przed GROUP BY; funkcje agregujące nie są dozwolone. HAVING: filtruje grupy po agregacji i jest jedynym miejscem, w którym warunek dotyczący wartości agregującej jest poprawny.
- Filtry dotyczące surowych kolumn należy umieszczać w WHERE, aby uzyskać większą szybkość i możliwość użycia indeksów.
- HAVING może odwoływać się do kolumn użytych do grupowania, ale nie powinno służyć do zwykłego filtrowania.
- HAVING działa bez GROUP BY na całej tabeli traktowanej jako jedna niejawna grupa.
- Dla zgodności między dialektami należy powtarzać wyrażenia agregujące w HAVING.
Często zadawane pytania
Czy lekcja „HAVING a WHERE” jest bezpłatna?
Tak — pełny tekst „HAVING a WHERE” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Coding Interview Prep, przejdź na CoddyKit PRO. Kurs Coding Interview Prep zawiera 4 lekcji w sumie.
Co nauczysz się w „HAVING a WHERE”?
Filtrowanie przed grupowaniem i po nim oraz klauzula, która ma dostęp do agregatu Ćwiczysz Coding Interview Prep z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Coding Interview Prep?
Nie wymagamy żadnego doświadczenia. Coding Interview Prep w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „HAVING a WHERE”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Coding Interview Prep?
Tak. Każda lekcja Coding Interview Prep zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Zasada GROUP BY dotycząca kolumn SELECT
- HAVING a WHERE
- Grupowanie według wielu kolumn i wyrażeń
- Zliczanie i filtrowanie grup