Jak używać funkcji agregujących dla podgrup danych?
Problem: Zapytanie z poprzedniej lekcji, np. SELECT AVG(Srednia) FROM Uczniowie;, zwraca średnią dla całej tabeli (całej szkoły). Co zrobić, gdy chcemy otrzymać średnią dla każdej klasy osobno (np. '3A', '3B', '3C') w jednym wyniku? Do tego służy klauzula GROUP BY.
Klauzula GROUP BY — opis działania
Klauzula GROUP BY instruuje bazę danych, aby podzieliła wiersze (po filtrze WHERE, jeśli jest użyty) na grupy na podstawie unikalnych wartości w podanej kolumnie (lub kolumnach). Dla każdej takiej grupy obliczane są następnie funkcje agregujące (np. AVG, COUNT, SUM), zamiast obliczeń dla całej tabeli.
W przykładzie poniżej GROUP BY Klasa tworzy osobną grupę dla wszystkich wierszy, gdzie Klasa = '3A', dla wszystkich z '3B' itd., a następnie liczy średnią i liczbę uczniów dla każdej grupy.
SELECT
Klasa,
AVG(Srednia) AS SredniaWKlasie,
COUNT(*) AS LiczbaUczniow
FROM Uczniowie
GROUP BY Klasa;
Przykładowy wynik:
- Klasa: '3A' — SredniaWKlasie: 4.15 — LiczbaUczniow: 30
- Klasa: '3B' — SredniaWKlasie: 3.98 — LiczbaUczniow: 28
- Klasa: '3C' — SredniaWKlasie: 4.30 — LiczbaUczniow: 31
Uwagi o funkcjach agregujących (COUNT, SUM, AVG) i ich zachowaniu z wartościami NULL są omówione w materiałach o funkcjach agregujących . Z kolei użycie agregacji razem z grupowaniem jest opisane w dalszych lekcjach dotyczących agregacji i GROUP BY .
Reguła SELECT z GROUP BY (najważniejsza zasada)
Główna zasada brzmi: gdy używasz GROUP BY, w klauzuli SELECT możesz umieścić jedynie:
- Kolumny, które występują w
GROUP BY(np.Klasa), - Funkcje agregujące (np.
AVG(Srednia),COUNT(*)).
Dlaczego? Ponieważ zapytanie zwraca po jednym wierszu na grupę. Jeżeli spróbujesz dodać kolumnę, która nie jest ani w GROUP BY, ani agregatem (np. Imie), to baza nie wie, którą wartość z wielu wierszy w danej grupie pokazać i zgłosi błąd.
-- BŁĘDNE zapytanie:
SELECT Imie, Klasa, AVG(Srednia)
FROM Uczniowie
GROUP BY Klasa;
-- Baza nie wie, które Imie pokazać dla grupy (np. '3A'), bo jest tam wiele imion.
Dodatkowe przykłady użycia (praktyczne przypadki)
Filtrowanie przed grupowaniem (WHERE):
SELECT Klasa, AVG(Srednia) AS Srednia FROM Uczniowie WHERE Rok = 2025 GROUP BY Klasa;Najpierw wybieramy tylko uczniów z 2025 roku, potem grupujemy po klasie i liczymy średnie.
Grupowanie po kilku kolumnach:
SELECT Rok, Klasa, AVG(Srednia) AS Srednia FROM Uczniowie GROUP BY Rok, Klasa;Tworzy grupy np. dla (Rok=2024, Klasa='3A'), (Rok=2024, Klasa='3B') itd.
Użycie HAVING do filtrowania grup:
SELECT Klasa, AVG(Srednia) AS Srednia, COUNT(*) AS Liczba FROM Uczniowie GROUP BY Klasa HAVING AVG(Srednia) > 4.0 AND COUNT(*) >= 20;HAVINGfiltruje już powstałe grupy (np. pokazuje tylko klasy ze średnią > 4.0 i conajmniej 20 uczniów).Porządkowanie wyników:
SELECT Klasa, AVG(Srednia) AS Srednia FROM Uczniowie GROUP BY Klasa ORDER BY Srednia DESC;Wyświetla klasy posortowane od najwyższej do najniższej średniej.
GROUP BY z COUNT(DISTINCT):
SELECT Klasa, COUNT(DISTINCT Miasto) AS LiczbaMiast FROM Uczniowie GROUP BY Klasa;Liczba różnych miast, z których pochodzą uczniowie danej klasy.
GROUP BY z JOIN (grupowanie po kolumnie z tabeli dołączonej):
SELECT K.NazwaKlasy, AVG(U.Srednia) AS Srednia FROM Uczniowie U JOIN Klasy K ON U.ID_Klasy = K.ID_Klasy GROUP BY K.NazwaKlasy;Przydatne, gdy nazwa klasy jest trzymana w osobnej tabeli Klasy.
Przykład praktyczny: statystyki pojedynczej klasy:
SELECT COUNT(*) AS LiczbaUczniow, AVG(Srednia) AS SredniaOcen, MAX(Srednia) AS Najwyzsza, MIN(Srednia) AS Najnizsza FROM Uczniowie WHERE Klasa = '3A';To zapytanie bez GROUP BY zwraca jedną linię ze statystykami dla klasy '3A' (pokazane tu jako alternatywa do grupowania).
Najczęściej popełniane błędy
- Umieszczanie w SELECT kolumn, które nie są w GROUP BY i nie są agregatami — powoduje błąd logiczny/wyjątek.
- Mylenie WHERE i HAVING — WHERE filtruje wiersze przed grupowaniem, HAVING filtruje już powstałe grupy.
- Nieprawidłowe użycie COUNT: pamiętaj, że
COUNT(*)liczy wszystkie wiersze, aCOUNT(kolumna)zlicza tylko nie-NULL wartości.
Materiały pomocnicze o funkcjach agregujących i grupowaniu można znaleźć w lekcjach dotyczących funkcji agregujących (COUNT, SUM, AVG) oraz MIN/MAX i grupowania .