SQL Funkcje Agregujące (COUNT, SUM, AVG, MIN, MAX)
Funkcje agregujące to potężne narzędzia w SQL, które pozwalają 'zwinąć' całą kolumnę (lub grupę wierszy) do *jednej* wartości. Zamiast pobierać tysiące pojedynczych wierszy, możesz natychmiast odpowiedzieć na pytania: 'Ile jest wszystkich produktów?' (`COUNT`), 'Jaka jest łączna wartość magazynu?' (`SUM`), 'Jaka jest średnia cena?' (`AVG`), 'Jaki jest najtańszy produkt?' (`MIN`) lub 'Jaki jest najdroższy produkt?' (`MAX`). Są to fundamentalne operacje, które pozwalają na analizę i tworzenie podsumowań danych. Na maturze są one absolutnie kluczowe do odpowiadania na pytania statystyczne.
Dlaczego to ważne? Na maturze bardzo rzadko jesteś proszony o wypisanie *wszystkich* danych. Zazwyczaj zadanie brzmi: 'Podaj *liczbę*...', 'Oblicz *sumę*...', 'Znajdź *największą*...'. Wszystkie te polecenia wprost sugerują użycie funkcji agregujących. Użyjesz ich w prawie każdym zadaniu SQL, najczęściej w połączeniu z `WHERE` (do filtrowania) lub `GROUP BY` (do tworzenia podsumowań dla grup).
Teoria
Funkcja agregująca wykonuje obliczenie na zestawie wierszy i zwraca *pojedynczą wartość*. Jest ona stosowana w klauzuli `SELECT` (aby wyświetlić wynik) lub `HAVING` (aby filtrować grupy na podstawie wyniku agregacji).
Jak to działa?
- `COUNT(*)`: Zlicza całkowitą liczbę wierszy w tabeli lub grupie.
- `COUNT(kolumna)`: Zlicza liczbę wierszy, w których `kolumna` ma wartość *inną niż NULL*.
- `SUM(kolumna)`: Sumuje wszystkie wartości w `kolumna`. Działa tylko dla typów numerycznych.
- `AVG(kolumna)`: Oblicza średnią arytmetyczną wartości w `kolumna`. Działa tylko dla typów numerycznych.
- `MIN(kolumna)`: Znajduje najmniejszą wartość w `kolumna` (działa na liczbach, tekstach i datach).
- `MAX(kolumna)`: Znajduje największą wartość w `kolumna` (działa na liczbach, tekstach i datach).
- Jeśli są użyte *bez* `GROUP BY`, działają na całej tabeli (po filtracji `WHERE`).
- Jeśli są użyte *z* `GROUP BY`, działają oddzielnie dla każdej utworzonej grupy.
Złożoność: Nie dotyczy w tradycyjnym sensie O(n). Wydajność zależy od konieczności przeskanowania całej tabeli lub grupy, ale na maturze są to zawsze operacje uważane za szybkie.
Implementacja
COUNT - Zliczanie wierszy
SQL-- Ilu jest wszystkich uczniów?
SELECT COUNT(*) AS LiczbaWszystkichUczniow
FROM Uczniowie;
-- Ilu uczniów jest w klasie '1A'?
SELECT COUNT(*)
FROM Uczniowie
WHERE klasa = '1A';
-- Ilu uczniów ma wpisany numer telefonu (pomija NULLe)?
SELECT COUNT(telefon)
FROM Uczniowie;`COUNT(*)` to najczęstszy sposób na policzenie 'ile czegoś jest'. `AS` służy do nadania przyjaznej nazwy kolumnie wynikowej. Zwróć uwagę na różnicę między `COUNT(*)` (liczy wiersze) a `COUNT(kolumna)` (liczy wartości nie-NULL).
SUM i AVG - Sumowanie i uśrednianie
SQL-- Jaka jest łączna cena wszystkich produktów?
SELECT SUM(cena) AS LacznaWartosc
FROM Produkty;
-- Jaka jest średnia cena produktów z kategorii 'Nabiał'?
SELECT AVG(cena) AS SredniaCenaNabialu
FROM Produkty
WHERE kategoria = 'Nabiał';`SUM` i `AVG` działają tylko na kolumnach numerycznych. Można je (i należy) łączyć z `WHERE`, aby obliczać statystyki tylko dla interesującego nas podzbioru danych.
MIN i MAX - Wartości skrajne
SQL-- Jaka jest cena najtańszego i najdroższego produktu?
SELECT MIN(cena) AS CenaMin, MAX(cena) AS CenaMax
FROM Produkty;
-- Kto jest pierwszy alfabetycznie na liście uczniów?
SELECT MIN(nazwisko) AS PierwszeNazwisko
FROM Uczniowie;`MIN` i `MAX` działają również na tekstach, sortując je alfabetycznie. `MIN(nazwisko)` da nazwisko najbliższe literze 'A', a `MAX(nazwisko)` - najbliższe 'Z'.
Przykładowe Zadania Maturalne
Masz tabelę 'Samochody' (rejestracja, marka, rok_produkcji, pojemnosc). Napisz zapytanie SQL, które obliczy i poda *średnią pojemność* (`pojemnosc`) wszystkich samochodów marki 'Ford'.
Wskazówka: Potrzebujesz funkcji agregującej `AVG()` zastosowanej do kolumny `pojemnosc`. Musisz też przefiltrować dane za pomocą `WHERE`, aby liczyć średnią tylko dla wierszy, gdzie `marka` to 'Ford'.
Pokaż szkic rozwiązania
1. Wybierz funkcję agregującą: `SELECT AVG(pojemnosc)` 2. Wskaż tabelę: `FROM Samochody` 3. Dodaj filtr: `WHERE marka = 'Ford';` 4. Pełne zapytanie: `SELECT AVG(pojemnosc) FROM Samochody WHERE marka = 'Ford';`
W bazie danych są tabele: 'Klienci' (id_klienta, imie, nazwisko), 'Wizyty' (id_wizyty, id_klienta, id_uslugi) oraz 'Uslugi' (id_uslugi, nazwa, cena). Podaj imię i nazwisko osoby, która wydała najwięcej na usługi fryzjerskie. Podaj również sumę jej wydatków.
Wskazówka: To złożone zadanie. Musisz: 1) Połączyć (JOIN) wszystkie 3 tabele. 2) Pogrupować (GROUP BY) wyniki po `id_klienta` (lub imieniu i nazwisku). 3) Obliczyć `SUM(Uslugi.cena)` dla każdej grupy. 4) Posortować (ORDER BY) wyniki malejąco (DESC) wg tej sumy. 5) Wybrać tylko pierwszy wiersz (LIMIT 1).
Pokaż szkic rozwiązania
1. Wybierz dane: `SELECT K.imie, K.nazwisko, SUM(U.cena) AS SumaWydatkow` 2. Wskaż tabele i połącz je: `FROM Klienci AS K JOIN Wizyty AS W ON K.id_klienta = W.id_klienta JOIN Uslugi AS U ON W.id_uslugi = U.id_uslugi` 3. Zgrupuj: `GROUP BY K.id_klienta, K.imie, K.nazwisko` 4. Posortuj malejąco: `ORDER BY SumaWydatkow DESC` 5. Wybierz tylko górny wiersz: `LIMIT 1;`
Częste Błędy
❌ Używanie `WHERE` zamiast `HAVING`
Chcesz znaleźć klasy z ponad 30 uczniami i piszesz: `... WHERE COUNT(*) > 30`. To błąd. `WHERE` filtruje *przed* agregacją. `COUNT` nie jest jeszcze znany.
Poprawka: Do filtrowania na wynikach funkcji agregujących (np. `COUNT`, `SUM`) służy klauzula `HAVING`. Poprawnie: `... GROUP BY klasa HAVING COUNT(*) > 30`.
❌ Mieszanie kolumn z agregatami (bez `GROUP BY`)
Piszesz: `SELECT klasa, COUNT(*) FROM Uczniowie;`. To błąd. Baza nie wie, którą 'klasę' ma wyświetlić obok ogólnej liczby *wszystkich* uczniów.
Poprawka: Jeśli w `SELECT` jest funkcja agregująca i zwykła kolumna, *musisz* dodać `GROUP BY` dla tej zwykłej kolumny: `SELECT klasa, COUNT(*) FROM Uczniowie GROUP BY klasa;`.
❌ Różnica między `COUNT(*)` a `COUNT(kolumna)`
Masz 100 uczniów, ale 10 nie ma wpisanego maila. `COUNT(*)` da 100. `COUNT(email)` da 90, ponieważ `COUNT(kolumna)` ignoruje wartości `NULL`.
Poprawka: Do liczenia wierszy *zawsze* używaj `COUNT(*)`. `COUNT(kolumna)` używaj tylko, gdy chcesz policzyć, ile jest *wypełnionych* (niepustych) pól w tej kolumnie.
❌ `AVG` na liczbach całkowitych (INT)
W niektórych systemach SQL, jeśli kolumna `cena` jest typu `INT`, `AVG(cena)` może zwrócić `INT` (np. 3 zamiast 3.5). To obcina wynik.
Poprawka: Na maturze zazwyczaj pracujesz na MySQL, który zwykle zwraca `float`. Aby być bezpiecznym, można rzutować: `AVG(CAST(cena AS DECIMAL(10,2)))` lub `AVG(cena * 1.0)`.
Kluczowe Wnioski
- Funkcje agregujące 'zwijają' wiele wierszy do jednej wartości.
- `COUNT(*)` - liczy wiersze.
- `SUM(kolumna)` - sumuje wartości w kolumnie.
- `AVG(kolumna)` - liczy średnią wartość w kolumnie.
- `MIN(kolumna)` / `MAX(kolumna)` - znajdują najmniejszą / największą wartość.
- Mogą być używane na całej tabeli (z `WHERE`) lub na grupach (z `GROUP BY`).
- `HAVING` to `WHERE` dla wyników funkcji agregujących (np. `HAVING SUM(cena) > 1000`).
Najczęściej Zadawane Pytania
❓ Jaka jest różnica między `COUNT(*)` a `COUNT(1)`?
W praktyce - żadna. Oba zliczają wszystkie wiersze w grupie. `COUNT(*)` jest bardziej standardowe i czytelne, ale oba działają tak samo szybko.
❓ Czy mogę użyć `AVG(SUM(cena))`?
Nie, nie można zagnieżdżać funkcji agregujących (np. 'średnia z sumy'). Takie operacje wykonuje się za pomocą zapytań zagnieżdżonych (podzapytań).
❓ Jak policzyć *unikalne* wartości w kolumnie?
Użyj słowa kluczowego `DISTINCT`. Na przykład: `SELECT COUNT(DISTINCT klasa) FROM Uczniowie;` policzy, ile jest różnych klas (np. '1A', '1B', '2A' -> 3).
❓ Co się stanie, jeśli użyję `SUM` na kolumnie tekstowej?
W większości systemów (jak MySQL) dostaniesz wynik 0 lub ostrzeżenie. Te funkcje działają tylko na danych numerycznych. Wyjątkiem są `MIN` i `MAX`, które działają na tekście (alfabetycznie).
Chcesz opanować wszystkie tematy maturalne?
Dołącz do kursu i zyskaj dostęp do interaktywnych lekcji, edytora kodu i setek zadań.