Funkcje agregujące zamieniają wiele wierszy w jedną wartość: liczbę zamówień, sumę sprzedanych sztuk, średnią cenę. Na lekcji uczniowie liczą statystyki małego sklepu i przy okazji odkrywają, jak funkcje agregujące traktują wartość NULL — to częsta pułapka w raportach.
Scenariusz jest przeznaczony na 45 minut dla klasy znającej SELECT i WHERE — na przykład po lekcji o WHERE. Grupowanie (GROUP BY) jest tematem osobnej lekcji.
Przygotowanie stanowisk
Potrzebna jest baza MySQL 8 lub MariaDB (na przykład w XAMPP) i narzędzie do wykonywania zapytań, np. phpMyAdmin. Utwórz pustą bazę ćwiczeniową i zaimportuj raz plik baza.sql z pakietu. Plik nie usuwa tabel, więc ponowny import zgłosi błąd istniejącej tabeli. Zapytania zapisuj w start.sql; rozwiązania są w rozwiazania.sql.
Cele i plan lekcji
Po zajęciach uczeń potrafi:
- użyć
COUNT(*),COUNT(kolumna),SUM,AVG,MINiMAX; - wyjaśnić, że funkcje agregujące pomijają
NULL, aCOUNT(*)liczy wszystkie wiersze; - obliczyć wartość wyrażenia (ilość razy cena) dla wszystkich wierszy;
- zastosować
WHERE, aby policzyć statystykę dla jednego klienta.
| Czas | Praca na lekcji |
|---|---|
| 0–5 min | Problem: ile sprzedano i za ile? |
| 5–15 min | COUNT, SUM, AVG, MIN, MAX |
| 15–22 min | NULL w agregatach i WHERE |
| 22–37 min | Pięć zadań samodzielnych |
| 37–42 min | Porównanie wyników, omówienie NULL |
| 42–45 min | Pytania kontrolne |
Tabela zamówienia
Kolumny: id, klient, produkt, ilosc (sztuki) i cena (zł za sztukę). W zamówieniu nr 6 nie zapisano ilości, więc jest tam NULL.
| id | klient | produkt | ilosc | cena |
|---|---|---|---|---|
| 1 | Anna | Mysz | 2 | 35 |
| 2 | Bartek | Kabel | 10 | 15 |
| 3 | Anna | Monitor | 1 | 650 |
| 4 | Celina | Kabel | 5 | 15 |
| 5 | Bartek | Mysz | 1 | 35 |
| 6 | Anna | Kabel | NULL | 15 |
| 7 | Damian | Laptop | 1 | 2400 |
Funkcje agregujące i NULL
COUNT(*) liczy wiersze, COUNT(kolumna) — wiersze, w których kolumna nie jest NULL. SUM sumuje, AVG liczy średnią, MIN i MAX zwracają najmniejszą i największą wartość. Wszystkie te funkcje (poza COUNT(*)) pomijają NULL. Dlatego średnia ilość to suma 20 sztuk podzielona przez 6 zamówień z wpisaną ilością, a nie przez 7. Wyrażenie ilosc * cena dla zamówienia bez ilości też daje NULL, więc nie wchodzi do sumy. ROUND(wyrażenie, 2) zaokrągla wynik; COUNT(DISTINCT kolumna) liczy różne wartości.
Bez GROUP BY zapytanie z funkcją agregującą zwraca jeden wiersz dla całej tabeli (lub dla wierszy wybranych przez WHERE).
Zadania
Zadanie 1. Policz wszystkie zamówienia oraz zamówienia z wpisaną ilością. Porównaj obie liczby.
Zadanie 2. Oblicz łączną liczbę sprzedanych sztuk i średnią ilość w zamówieniu zaokrągloną do dwóch miejsc.
Zadanie 3. Wyznacz najniższą i najwyższą cenę.
Zadanie 4. Oblicz łączną wartość zamówień (ilosc * cena).
Zadanie 5. Policz zamówienia i łączną ilość sztuk dla klienta Anna.
Dla chętnych: policz, ilu różnych klientów złożyło zamówienia (COUNT(DISTINCT klient)).
Rozwiązanie i wyniki
-- Zadanie 1
SELECT COUNT(*) AS wszystkie, COUNT(ilosc) AS z_iloscia
FROM zamowienia;
-- Zadanie 2
SELECT SUM(ilosc) AS sztuki, ROUND(AVG(ilosc), 2) AS srednia
FROM zamowienia;
-- Zadanie 3
SELECT MIN(cena) AS najnizsza, MAX(cena) AS najwyzsza
FROM zamowienia;
-- Zadanie 4
SELECT SUM(ilosc * cena) AS wartosc
FROM zamowienia;
-- Zadanie 5
SELECT COUNT(*) AS zamowienia, SUM(ilosc) AS sztuki
FROM zamowienia
WHERE klient = 'Anna';
-- Dla chetnych
SELECT COUNT(DISTINCT klient) AS klienci
FROM zamowienia;
Wyniki (sprawdzone na SQLite z tą samą tabelą):
| Zadanie | Wynik |
|---|---|
| 1 | wszystkie = 7, z ilością = 6 |
| 2 | sztuki = 20, średnia = 3.33 |
| 3 | najniższa = 15, najwyższa = 2400 |
| 4 | wartość = 3380 zł |
| 5 | zamówienia = 3, sztuki = 3 |
| Dla chętnych | klienci = 4 |
W zadaniu 2 średnia 3,33 to 20 : 6 — zamówienie bez ilości zostało pominięte. W zadaniu 5 Anna ma trzy zamówienia, ale tylko dwa z ilością (2 + 1 = 3 sztuki), dlatego COUNT(*) i SUM(ilosc) dają obie liczbę 3 przez przypadek; warto to omówić z uczniami. Wartość zamówień 3380 zł to 70 + 150 + 650 + 75 + 35 + 2400 (zamówienie z NULL nie wchodzi do sumy).
Typowe błędy
| Objaw | Co sprawdzić |
|---|---|
| Średnia wychodzi za niska | Za NULL podstawiono 0 albo podzielono przez COUNT(*) zamiast liczby wpisanych wartości. |
COUNT(ilosc) daje inny wynik niż COUNT(*) | To zamierzone: COUNT(kolumna) pomija NULL. |
| Błąd: mieszanie kolumny i funkcji agregującej | Bez GROUP BY w SELECT nie wolno łączyć zwykłej kolumny z funkcją agregującą. |
| SUM zwraca NULL | W wybranych wierszach wszystkie wartości są NULL albo WHERE nic nie wybiera. |
| Wartość zamówień zawyżona | Zsumowano samą cenę zamiast ilosc * cena. |
WHERE użyty po funkcji | WHERE stoi po FROM, a nie obok funkcji w SELECT. |
Pytania kontrolne i punktacja
- Czym różni się
COUNT(*)odCOUNT(ilosc)? - Jak funkcja
AVGtraktuje wartościNULL? - Jaki wynik da
SELECT MAX(cena) FROM zamowienia WHERE klient = 'Damian'dla danych z lekcji?
Odpowiedzi: COUNT(*) liczy wszystkie wiersze, COUNT(ilosc) tylko te, w których ilość nie jest NULL. Pomija je (nie wlicza ich do licznika ani do mianownika). 2400.
Proponowana punktacja (razem 10 punktów): zadanie 1 — dwa COUNT 2 pkt; zadanie 2 — SUM i AVG z ROUND 2 pkt; zadanie 3 — MIN i MAX 2 pkt; zadanie 4 — suma iloczynów 2 pkt; zadanie 5 — WHERE z agregatami 2 pkt. Zadanie dla chętnych nie jest wymagane do pełnej oceny.
Materiały do pobrania
Rozpakuj ZIP przed otwarciem plików. Materiały są dostępne bez logowania; publiczne rozwiązanie służy nauce i samodzielnemu sprawdzeniu, a nie poufnemu sprawdzianowi.
Co dalej?
Następny krok to GROUP BY i HAVING, które liczą statystyki osobno dla każdego klienta lub produktu. Ten materiał rozwija dział o agregowaniu danych w kursie SQL w TablicaPro, gdzie znajdziesz prezentacje, ćwiczenia i testy do prowadzenia lekcji.
Źródła techniczne: funkcje agregujące w dokumentacji MySQL. Zobacz też lekcję o GROUP BY.
Poprowadź kolejne lekcje SQL
Pełny kurs: prezentacje, ćwiczenia i testy do pracy z klasą.
Kup dostęp do kursu SQL →