Przejdź do treści

Listopadowa cena: matura z informatyki za 100 zł zamiast 120 zł za lekcję. Zgłoś się do 30.11. Umów bezpłatną konsultację →

Dział IV

Bazy Danych: Agregacja i Grupowanie

Sumy, średnie i liczniki w podziale na grupy: wiersz Podsumowanie w siatce, GROUP BY i HAVING w SQL oraz to, jak agregaty traktują wartości puste.

Wstęp: od listy rekordów do wniosków

Dopóki kwerenda wypisuje rekordy, odpowiada na pytanie „kto”. Agregacja odpowiada na pytania „ile” i „średnio”: ile zamówień złożył każdy klient, jaka jest średnia ocena w klasie, który miesiąc przyniósł największy obrót. To najczęściej punktowana część zadania z bazy danych, bo jedno zapytanie zastępuje ręczne liczenie w arkuszu.

1 Włączenie podsumowań i wiersz Suma

W siatce projektowej agregację włącza przycisk Sumy (ikona greckiej sigmy) na wstążce. W siatce pojawia się wtedy dodatkowy wiersz Podsumowanie, a każda kolumna dostaje wybór: albo służy do grupowania, albo jest liczona jedną z funkcji, albo jest tylko warunkiem filtrującym.

Trzy ustawienia w wierszu Podsumowanie
  • Grupuj według — kolumna dzieli wynik na grupy, na przykład po nazwisku klienta albo po miesiącu.
  • Suma, Średnia, Policz, Min, Maks — kolumna jest liczona wewnątrz każdej grupy.
  • Gdzie — kolumna służy wyłącznie do filtrowania przed zgrupowaniem i nie pojawia się w wyniku.
-- ta sama kwerenda zapisana w SQL
SELECT k.Nazwisko,
     COUNT(*) AS Liczba_zamowien,
     SUM(z.Wartosc) AS Laczna_wartosc
FROM Klienci AS k
INNER JOIN Zamowienia AS z ON k.ID = z.ID_klienta
GROUP BY k.Nazwisko
ORDER BY SUM(z.Wartosc) DESC;

2 Co grupujesz, a co liczysz

Reguła jest jedna i nie ma od niej wyjątków: każda kolumna w wyniku musi być albo polem grupującym, albo wynikiem funkcji agregującej. Jeśli spróbujesz dołożyć zwykłe pole, na przykład numer pojedynczego zamówienia, obok sumy wartości, baza nie będzie wiedziała, który z wielu numerów w grupie pokazać.

Objaw błędu

Access zamiast jednego wiersza na klienta pokaże ich kilkanaście — bo zgrupował po dwóch kolumnach naraz, a druga z nich jest niemal unikalna. W standardowym SQL zobaczysz komunikat, że pole nie występuje w GROUP BY. Rozwiązanie jest to samo: albo usuń tę kolumnę, albo dopisz ją do grupowania, świadomie zmieniając sens zapytania.

Grupowanie po fragmencie danych

Polecenie „podaj obrót w kolejnych miesiącach” wymaga grupowania po wartości wyliczonej, nie po surowej dacie — inaczej każda data będzie osobną grupą.

SELECT YEAR(Data) AS Rok,
     MONTH(Data) AS Miesiac,
     SUM(Wartosc) AS Obrot
FROM Zamowienia
GROUP BY YEAR(Data), MONTH(Data)
ORDER BY Rok, Miesiac;

3 Funkcje agregujące i wartości puste

Funkcja i jej sens
  • COUNT(*) — liczba rekordów w grupie
  • COUNT(pole) — liczba uzupełnionych wartości
  • SUM, AVG — suma i średnia
  • MIN, MAX — skrajne wartości
Zachowanie przy pustych polach
  • agregaty pomijają wartości puste
  • średnia z pięciu ocen, gdy dwie są puste, liczy się z trzech
  • COUNT(*) policzy wszystkie pięć rekordów
  • różnica między tymi dwoma licznikami to gotowa odpowiedź na pytanie o braki w danych
-- ilu uczniow w klasie i ilu ma wpisana ocene
SELECT Klasa,
     COUNT(*) AS Uczniow,
     COUNT(Ocena) AS Z_ocena,
     AVG(Ocena) AS Srednia
FROM Uczniowie
GROUP BY Klasa;

-- liczba roznych miast, a nie liczba klientow
-- UWAGA: Access nie zna zapisu COUNT(DISTINCT pole) -- trzeba przez podzapytanie
SELECT COUNT(*) AS Liczba_miast
FROM (SELECT DISTINCT Miasto FROM Klienci) AS m;
Pułapka: DISTINCT wewnątrz funkcji

Znany z kursów SQL zapis COUNT(DISTINCT Miasto) działa w większości baz danych, ale nie w Accessie — zwróci komunikat o błędzie składni. Na egzaminie liczysz różne wartości w dwóch krokach: kwerenda z DISTINCT jako źródło, a na niej zwykłe COUNT(*). W LibreOffice Base pierwotny zapis jest poprawny.

Średnia liczona na piechotę bywa inna

Jeśli w zadaniu wynik z bazy różni się od tego, co policzyłeś w arkuszu, prawie zawsze winne są puste komórki albo kolumna wczytana jako tekst. Zanim uznasz, że zapytanie jest złe, porównaj COUNT(*) z COUNT(pole) — to pięć sekund, a wskazuje przyczynę.

4 Filtr przed grupowaniem i po grupowaniu

To rozróżnienie decyduje o poprawności całego zadania. Warunek na pojedynczych rekordach działa przed zgrupowaniem i trafia do WHERE. Warunek na wyniku funkcji agregującej działa po zgrupowaniu i trafia do HAVING. W siatce projektowej odpowiada temu ustawienie w wierszu Podsumowanie: „Gdzie” filtruje przed, kryterium przy kolumnie liczonej filtruje po.

-- tylko zamowienia z 2026 roku (filtr na rekordach),
-- a potem klienci z laczna kwota powyzej 5000 (filtr na grupach)
SELECT k.Nazwisko, SUM(z.Wartosc) AS Razem
FROM Klienci AS k
INNER JOIN Zamowienia AS z ON k.ID = z.ID_klienta
WHERE YEAR(z.Data) = 2026
GROUP BY k.Nazwisko
HAVING SUM(z.Wartosc) > 5000
ORDER BY Razem DESC;
Test na rozpoznanie

Zadaj sobie pytanie: czy warunek da się sprawdzić, patrząc na jeden wiersz danych? „Zamówienie z maja” — tak, to WHERE. „Klient, który złożył więcej niż trzy zamówienia” — nie, bo trzeba najpierw policzyć całą grupę, więc HAVING.

5 „Kto ma najwięcej” w dwóch krokach

Polecenia typu „podaj klienta o największej łącznej wartości zamówień” kuszą do napisania jednego skomplikowanego zapytania. Na egzaminie szybszy i pewniejszy jest rozbieg na dwie kwerendy: pierwsza liczy sumy, druga sortuje wynik pierwszej i bierze wierzchołek. Access pozwala użyć zapisanej kwerendy jako źródła danych dokładnie tak jak tabeli.

-- krok 1: zapisz jako Kwerenda_sumy
SELECT ID_klienta, SUM(Wartosc) AS Razem
FROM Zamowienia
GROUP BY ID_klienta;

-- krok 2: najwiekszy wynik
SELECT TOP 1 k.Nazwisko, s.Razem
FROM Kwerenda_sumy AS s
INNER JOIN Klienci AS k ON k.ID = s.ID_klienta
ORDER BY s.Razem DESC;
Remis na pierwszym miejscu

Gdy dwóch klientów ma identyczną sumę, zapytanie z ograniczeniem do jednego wiersza w Accessie zwróci obu, bo program nie rozstrzyga remisów. To zwykle dobrze, bo polecenie oczekuje wszystkich rekordów o maksymalnej wartości. Jeśli jednak arkusz prosi o jedną osobę, dołóż drugie kryterium sortowania, na przykład alfabetyczne.

6 Kontrola wyniku

  • Liczba grup. Jeśli grupujesz po klasie, a wyników jest tyle, ile uczniów, do grupowania wkradła się zbędna kolumna.
  • Suma kontrolna. Suma wszystkich grup musi równać się sumie całej kolumny bez grupowania. Różnica oznacza, że filtr odciął część rekordów.
  • Nazwy kolumn. Access nazywa pola automatycznie, na przykład SumaOfWartosc. Gdy polecenie podaje nazwę, ustaw ją ręcznie przez AS albo dwukropek.
  • Zaokrąglenie średniej. Jeśli arkusz prosi o dwa miejsca po przecinku, zaokrąglij w zapytaniu, a nie tylko w formatowaniu.

7 Podsumowanie całej tabeli, bez grupowania

Gdy polecenie pyta o jedną liczbę dla całego zbioru — łączny obrót, liczbę rekordów, najstarszą datę — grupowanie nie jest potrzebne. Wystarczy sama funkcja agregująca; wynik to jeden wiersz.

SELECT COUNT(*) AS Ile_zamowien,
     SUM(Wartosc) AS Obrot,
     MIN(Data) AS Pierwsze,
     MAX(Data) AS Ostatnie
FROM Zamowienia;

8 Kwerenda krzyżowa: tabela przestawna w bazie

Polecenie „zestaw sprzedaż w układzie miesiąc kontra kategoria” prosi o wynik dwuwymiarowy: jedna wartość dzieli wiersze, druga tworzy kolumny. W Accessie robi to kwerenda krzyżowa (Kreator kwerend → Kwerenda krzyżowa), gdzie wskazujesz trzy role: nagłówek wiersza, nagłówek kolumny i wartość.

Nagłówek wiersza — na przykład miesiąc. Może być ich kilka.
Nagłówek kolumny — dokładnie jeden, na przykład kategoria produktu.
Wartość — funkcja agregująca, najczęściej suma albo licznik.
Jeśli kolumn robi się kilkadziesiąt, to znak, że jako nagłówek kolumny wskazałeś pole niemal unikalne. Zamień je na wartość wyliczoną, na przykład rok zamiast pełnej daty.
Gdy kreatora nie ma

W programach bez kwerendy krzyżowej ten sam efekt uzyskasz sumą warunkową: każda kolumna to osobne wyrażenie liczące tylko wybraną kategorię.

-- standardowy SQL (LibreOffice Base)
SELECT MONTH(Data) AS Miesiac,
     SUM(CASE WHEN Kategoria = 'AGD' THEN Wartosc ELSE 0 END) AS AGD,
     SUM(CASE WHEN Kategoria = 'RTV' THEN Wartosc ELSE 0 END) AS RTV
FROM Zamowienia
GROUP BY MONTH(Data)
ORDER BY Miesiac;

-- to samo w Accessie: zamiast CASE WHEN funkcja IIf
SELECT Month([Data]) AS Miesiac,
     Sum(IIf([Kategoria]='AGD'; [Wartosc]; 0)) AS AGD,
     Sum(IIf([Kategoria]='RTV'; [Wartosc]; 0)) AS RTV
FROM Zamowienia
GROUP BY Month([Data]);

Access nie zna konstrukcji CASE WHEN — jej odpowiednikiem jest trzyargumentowa funkcja IIf ze średnikami. Warto znać oba zapisy, bo lista oprogramowania CKE dopuszcza oba pakiety, a wybór środowiska należy do zdającego.

Jak to ćwiczyć

Weź bazę z dowolnego arkusza i odpowiedz na cztery pytania jednym zapytaniem każde: ile rekordów w każdej grupie, jaka jest średnia, które grupy przekraczają próg, kto jest na szczycie. Za każdym razem zapisz wersję z siatki i wersję SQL. Po czterech powtórzeniach schemat GROUP BY plus HAVING wchodzi w nawyk.

Korepetycje z informatyki

Zdajesz maturę rozszerzoną z informatyki?

Prowadzimy indywidualne przygotowanie do matury z informatyki — algorytmy, Python i C++, bazy danych i arkusz kalkulacyjny. Zajęcia online, na arkuszach CKE. Zobacz program i cennik.

Zobacz korepetycje z informatyki

Uczysz się w technikum informatycznym? Prowadzimy też przygotowanie do kwalifikacji INF.02, INF.03 i INF.04. Zobacz egzaminy zawodowe →