Funkcje agregujące: COUNT, SUM, AVG, MIN i MAX
Podsumuj wiele rekordów jednym wynikiem. Rozróżniaj COUNT(*), COUNT(kolumna), DISTINCT i wpływ NULL na średnią.
Część bazodanowa INF.03Od wielu wierszy do jednej informacji
Funkcja agregująca podsumowuje zbiór wierszy. COUNT odpowiada „ile?”, SUM „jaka suma?”, AVG „jaka średnia?”, MIN i MAX „jaka najmniejsza i największa wartość?”. Bez GROUP BY cały zbiór po WHERE stanowi jedną grupę. To inna rola niż ROUND(cena,2), które oblicza wynik osobno dla wartości ceny.
SELECT COUNT(*) AS produkty,
SUM(cena) AS suma_cen,
AVG(cena) AS srednia_cena,
MIN(cena) AS najtaniej,
MAX(cena) AS najdrozej
FROM produkty;Po resecie otrzymasz jeden wiersz: 4, 1005, 251.25, 25, 800. Suma cen katalogowych nie oznacza wartości sprzedaży: ta wymaga także liczby sprzedanych sztuk i właściwego złączenia. Nazwa aliasu powinna mówić, co faktycznie policzyłeś.
COUNT(*) i COUNT(kolumna) liczą co innego
SELECT COUNT(*) AS klienci,
COUNT(email) AS z_emailem,
COUNT(*) - COUNT(email) AS bez_emaila
FROM klienci;Wynik: 5, 3, 2. COUNT(*) liczy wiersze; COUNT(email) tylko wiersze, w których email nie jest NULL. Pusty napis jest wartością tekstową w SQLite/MySQL/SQL Server, więc też zostaje policzony. Oracle traktuje pusty napis jako NULL. COUNT(1) również liczy wszystkie wiersze, bo stała 1 nigdy nie jest NULL; nie potrzebujesz tego zapisu zamiast czytelnego COUNT(*).
Wypróbuj zapytanie
SQLite — rzeczywisty silnik przeglądarki. MySQL / SQL Server — ograniczona emulacja składni. Wybierz tryb SQLite do natywnego LIKE. Pozostałe tryby nie są rzeczywistymi serwerami. Ścisłe typy, auto-ID i administrację ćwicz w prawdziwym SZBD.
NULL, zero i pusty zbiór
SUM, AVG, MIN i MAX pomijają NULL w argumentach. AVG dla 10, NULL, 20 daje 15: dzieli sumę 30 przez dwie znane wartości. Zastąpienie NULL zerem przed AVG zmieniłoby średnią na 10 i oznaczałoby nowe założenie o danych. Nie wykonuj takiej zamiany mechanicznie.
SELECT COUNT(*) AS liczba, SUM(cena) AS suma, AVG(cena) AS srednia
FROM produkty WHERE cena < 0;Po resecie żaden produkt nie spełnia warunku. Mimo tego agregacja bez GROUP BY zwraca jeden wiersz: 0, NULL, NULL. Gdy raport ma pokazywać sumę pustego zbioru jako 0, użyj COALESCE(SUM(cena),0). To świadoma reguła prezentacji. Przy grupowaniu pusty zbiór nie tworzy żadnej grupy.
DISTINCT wewnątrz agregacji
-- MySQL / MariaDB, SQL Server, Oracle, SQLite
SELECT COUNT(DISTINCT miasto) AS rozne_miasta FROM klienci;Wynik to 3: Gdansk, Krakow i Torun. NULL nie jest liczony przez COUNT(kolumna). DISTINCT przed listą SELECT usuwa identyczne wiersze wyniku; wewnątrz COUNT usuwa powtórzone wartości argumentu przed liczeniem. To nie to samo miejsce działania.
Access nie obsługuje tej formy COUNT(DISTINCT …). Utwórz zapisaną kwerendę qMiasta:
SELECT DISTINCT miasto FROM klienci WHERE miasto IS NOT NULL;Następnie policz jej rekordy: SELECT COUNT(*) AS rozne_miasta FROM qMiasta;. Zapisana kwerenda jest źródłem następnej kwerendy, nie nową kopią danych.
Te same funkcje, różne typy wyniku
Podstawowe zapytanie z COUNT/SUM/AVG/MIN/MAX działa w MySQL/MariaDB, SQL Server, Oracle i Access. Szczegóły typów oraz zakresy liczb nie są jednak identyczne. SQL Server AVG(int) zwraca int, więc średnia całkowitych 1 i 2 nie zachowa ułamka. Gdy ułamek jest potrzebny, rzutuj argument przed agregacją:
-- Rzeczywisty SQL Server
SELECT AVG(CAST(ilosc AS decimal(12,2))) AS srednia_ilosc
FROM pozycje;SQLite AVG zwraca liczbę rzeczywistą. To jedna z przyczyn, dla których emulacja składni nie zastępuje testu typów serwera. W edytorze użyj natywnego SQLite do doświadczeń liczbowych; ceny są REAL. Dla cen DECIMAL w produkcyjnej bazie sprawdź precyzję, skalę i możliwe przepełnienie SUM. W SQL Server COUNT ma zakres int; dla ogromnych zbiorów istnieje COUNT_BIG.
Najczęstsza pułapka: nazwa przy MAX
SELECT nazwa, MAX(cena) FROM produkty; nie jest przenośnym sposobem znalezienia najdroższego produktu. Nieagregowana nazwa nie została pogrupowana. Niektóre silniki odrzucą zapis, a SQLite ma szczególne reguły dla takich kolumn, które nie są zasadą całego SQL. Użyj ORDER BY cena DESC, id i limitu z poprzedniej lekcji albo porównania ceny do podzapytania MAX, które poznamy później. Podzapytanie może zachować wszystkie remisy.
Ćwiczenia
- Policz zamówienia ze statusem opłacone (w SQL wpisz dokładnie
'oplacone'). - Znajdź średnią i sumę cen produktów kosztujących co najmniej 100.
- Policz klientów bez podanego miasta na dwa sposoby.
Rozwiązania
SELECT COUNT(*) AS oplacone FROM zamowienia WHERE status = 'oplacone';
SELECT AVG(cena) AS srednia, SUM(cena) AS suma FROM produkty WHERE cena >= 100;
SELECT COUNT(*) AS brak_miasta FROM klienci WHERE miasto IS NULL;
SELECT COUNT(*) - COUNT(miasto) AS brak_miasta FROM klienci;Wyniki: 2 zamówienia; średnia 460 i suma 920; jeden klient bez miasta (Ewa). WHERE ogranicza wiersze przed obliczeniem agregacji.
Zapamiętaj: nazwij zbiór, który podsumowujesz, ustal znaczenie NULL i jednostkę wyniku. Dopiero potem wybierz funkcję.
Źródła: MySQL — agregacje, SQL Server AVG i typ wyniku, Oracle — agregacje, Access COUNT. INF.03.4: zestawienia danych. Dalej: GROUP BY i HAVING.

