Jak policzyć wiersze, zsumować i uśrednić wartości, jak podzielić tabelę na grupy przez GROUP BY, czym różni się HAVING od WHERE oraz funkcje tekstowe, liczbowe i daty w MySQL. Lekcja 8.5 kursu INF.03.
Funkcja agregująca liczy JEDNĄ wartość z wielu wierszy: ile ich jest, ile wynosi suma, jaka jest średnia. Razem z GROUP BY (GRUPUJ WEDŁUG) pozwala odpowiedzieć na pytania w rodzaju „ile produktów jest w każdej kategorii". Na egzaminie pisemnym wracają dwa tematy z tej lekcji: różnica między COUNT(*) a COUNT(kolumna) przy wartościach NULL oraz różnica między WHERE a HAVING. Informator CKE wymienia „wykorzystanie funkcji agregujących" wprost jako temat zadania praktycznego.
Tabela do przykładów
[ TABELA PRODUKT ]
id
nazwa
cena
kategoria
sztuk
1
Klawiatura
120
akcesoria
15
2
Mysz
45
akcesoria
0
3
Monitor 24
650
monitory
4
4
Monitor 27
990
monitory
2
5
Kabel HDMI
25
akcesoria
NULL
Pięć funkcji agregujących
Funkcja
Znaczy
Zapytanie
Wynik
COUNT
policz
SELECT COUNT(*) FROM produkt;
5
SUM
suma
SELECT SUM(cena) FROM produkt;
1830
AVG
średnia
SELECT AVG(cena) FROM produkt;
366
MIN
najmniejsza
SELECT MIN(cena) FROM produkt;
25
MAX
największa
SELECT MAX(cena) FROM produkt;
990
Bez GROUP BY funkcja liczy z CAŁEJ tabeli i zwraca jeden wiersz. MIN i MAX działają też na tekście (alfabetycznie) i na datach (najwcześniejsza i najpóźniejsza).
Wynik warto nazwać, bo domyślna nazwa kolumny to całe wyrażenie:
SELECT COUNT(*) AS ile, AVG(cena) AS srednia FROM produkt;
COUNT(*) kontra COUNT(kolumna)
To jedno z najczęstszych pytań o NULL.
Zapytanie
Wynik
Dlaczego
SELECT COUNT(*) FROM produkt;
5
liczy WIERSZE, niezależnie od zawartości
SELECT COUNT(sztuk) FROM produkt;
4
pomija wiersz, w którym sztuk jest NULL
SELECT COUNT(DISTINCT kategoria) FROM produkt;
2
liczy różne wartości: akcesoria, monitory
Pozostałe funkcje też pomijają NULL. Dlatego AVG(sztuk) z naszej tabeli to (15 + 0 + 4 + 2) podzielone przez 4, czyli 5,25, a nie przez 5. Zero jest wartością i wchodzi do rachunku; NULL nie.
Pułapka:COUNT(*) liczy wiersze, COUNT(kolumna) liczy wiersze z WYPEŁNIONĄ kolumną. Jeżeli pytanie pokazuje tabelę z pustymi polami, te dwie odpowiedzi będą różne i o to właśnie chodzi.
GROUP BY: podział na grupy
GROUP BY dzieli wiersze na grupy według wartości kolumny, a funkcja agregująca liczy osobno w każdej grupie.
SELECT kategoria, COUNT(*) AS ile, AVG(cena) AS srednia
FROM produkt
GROUP BY kategoria;
kategoria
ile
srednia
akcesoria
3
63.33
monitory
2
820.00
Trzy kroki grupowania: pięć wierszy tabeli, podział na dwie grupy według kategorii, jeden wiersz wyniku na grupę
Zasada, która rozstrzyga większość pytań: w SELECT mogą stać tylko kolumny wymienione w GROUP BY oraz funkcje agregujące. Zapytanie SELECT nazwa, COUNT(*) FROM produkt GROUP BY kategoria; jest błędne, bo w grupie „akcesoria" są trzy różne nazwy i baza nie wie, którą pokazać.
Grupować można po kilku kolumnach naraz: GROUP BY kategoria, sztuk tworzy grupę dla każdej pary wartości.
W przeglądarce usuń GROUP BY i wykonaj zapytanie ponownie, potem dopisz HAVING COUNT(*) >= 3:
Oba filtrują, ale w innym momencie i na innym poziomie.
SELECT kategoria, COUNT(*) AS ile
FROM produkt
WHERE cena > 30 -- odrzuca WIERSZE przed grupowaniem
GROUP BY kategoria
HAVING COUNT(*) >= 2; -- odrzuca GRUPY po policzeniu
Kolejność wykonania w bazie: FROM, WHERE, GROUP BY, funkcje agregujące, HAVING, SELECT, ORDER BY, LIMIT. Stąd dwie konsekwencje, o które pytają arkusze:
›
W WHERE nie wolno użyć funkcji agregującej. W momencie, gdy działa WHERE, grup jeszcze nie ma, więc WHERE COUNT(*) > 2 to błąd składni.
›
W HAVING wolno użyć funkcji agregującej, bo grupy są już policzone. Można tam też postawić zwykły warunek, ale filtrowanie pojedynczych wierszy należy do WHERE i jest szybsze.
Chcesz
Użyj
odrzucić produkty tańsze niż 30 zł
WHERE cena >= 30
zostawić kategorie mające co najmniej 2 produkty
HAVING COUNT(*) >= 2
zostawić kategorie o średniej cenie powyżej 100 zł
HAVING AVG(cena) > 100
Sortowanie po wyniku funkcji działa normalnie, także po nazwie nadanej przez AS:
SELECT kategoria, SUM(cena) AS wartosc
FROM produkt
GROUP BY kategoria
ORDER BY wartosc DESC;
Funkcje tekstowe, liczbowe i daty
Poza agregującymi MySQL ma funkcje działające na POJEDYNCZEJ wartości, wiersz po wierszu. Na egzaminie pojawiają się w pytaniach „co zwróci funkcja".
Funkcja
Co robi
Przykład
Wynik
CONCAT(a, b)
skleja teksty
CONCAT('Monitor', ' 24')
Monitor 24
UPPER(t) / LOWER(t)
wielkie i małe litery
UPPER('mysz')
MYSZ
LENGTH(t)
długość w bajtach; CHAR_LENGTH w znakach
CHAR_LENGTH('Mysz')
4
SUBSTRING(t, od, ile)
wycinek tekstu, liczony od 1
SUBSTRING('Klawiatura', 1, 4)
Klaw
REPLACE(t, co, czym)
podmiana fragmentu
REPLACE('Monitor 24', '24', '27')
Monitor 27
TRIM(t)
usuwa spacje z brzegów
TRIM(' mysz ')
mysz
ROUND(x, n)
zaokrągla do n miejsc
ROUND(63.333, 2)
63.33
CEIL(x) / FLOOR(x)
w górę i w dół do całości
CEIL(63.1)
64
MOD(a, b)
reszta z dzielenia
MOD(7, 2)
1
NOW()
data i godzina teraz
NOW()
2026-09-07 12:30:00
CURDATE()
dzisiejsza data
CURDATE()
2026-09-07
YEAR(d), MONTH(d), DAY(d)
część daty
YEAR('2026-09-07')
2026
DATEDIFF(a, b)
różnica w dniach
DATEDIFF('2026-09-10', '2026-09-07')
3
Funkcje można zagnieżdżać i łączyć z agregującymi: ROUND(AVG(cena), 2) daje średnią zaokrągloną do groszy, co w zadaniach wygląda znacznie lepiej niż 63.333333.
Na egzaminie
Pytania pisemne: „Które zapytanie zwróci liczbę uczniów w każdej klasie" (odpowiedź z GROUP BY), „Co zwróci COUNT(ocena), gdy dwa pola są puste", „Którą klauzulą filtruje się grupy" (odpowiedź HAVING) oraz rachunki z funkcji tekstowych, gdzie trzeba policzyć znaki albo wskazać wynik SUBSTRING.
W części praktycznej funkcja agregująca pojawia się w kwerendzie opisanej słowami: „wyświetl liczbę wycieczek w każdym kraju" albo „podaj średnią cenę noclegu". Wzorzec jest zawsze ten sam: kolumna grupująca w SELECT i w GROUP BY, funkcja obok niej.
Ściąga
Rzecz
Zapamiętaj
liczba wierszy
COUNT(*); z pominięciem NULL: COUNT(kolumna)
suma, średnia, skrajne
SUM, AVG, MIN, MAX; wszystkie pomijają NULL
podział na grupy
GROUP BY kolumna
co wolno w SELECT
kolumny z GROUP BY i funkcje agregujące
filtr wierszy
WHERE, przed grupowaniem, bez funkcji agregujących
filtr grup
HAVING, po grupowaniu, z funkcjami agregującymi
kolejność
FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY, LIMIT