Wyobraź sobie, że masz w sklepie muzycznym tysiące danych: klienci, produkty, zamówienia, ceny, ilości…
Chcesz znaleźć odpowiedź na pytania w rodzaju:
- Który klient wydał najwięcej pieniędzy?
- Ile wynosi średnia wartość zamówienia w każdej kategorii?
- Które produkty nie zostały jeszcze zamówione?
Do tego właśnie służą zapytania złożone – czyli takie, które łączą kilka elementów SQL:JOIN, GROUP BY, HAVING, ORDER BY, a czasem także podzapytania.
1. Co to są zapytania złożone?
Zapytania złożone to po prostu kombinacja kilku operacji w jednym zapytaniu.
Zazwyczaj:
- pobieramy dane z kilku tabel (JOIN),
- grupujemy je (GROUP BY),
- wykonujemy obliczenia (SUM, COUNT, AVG),
- filtrujemy wyniki (HAVING, WHERE),
- sortujemy (ORDER BY).
Ich siła polega na tym, że możemy w jednym poleceniu uzyskać pełny raport z bazy danych.
2. Przykładowa baza: sklep muzyczny
Użyjemy bazy, którą znasz:
- Klienci – dane o klientach
- Produkty – dane o produktach
- Zamowienia – dane o zakupach
3. Struktura zapytania złożonego
Zapytanie złożone zazwyczaj ma taką kolejność:
SELECT kolumny, funkcje_agregujące
FROM tabela
JOIN inne_tabele
ON warunki_połączenia
WHERE warunki_filtrowania
GROUP BY kolumny
HAVING warunki_dla_grup
ORDER BY kolumny ASC|DESC
LIMIT liczba_wierszy;
Każdy etap robi coś innego i zawsze wykonuje się w tej kolejności.
To bardzo ważne, żeby uczniowie to zapamiętali.
4. Przykłady zapytań złożonych
a) Kto złożył zamówienie i co kupił
SELECT k.imie, k.nazwisko, p.nazwa, z.ilosc, (z.ilosc * p.cena) AS wartosc
FROM Zamowienia z
JOIN Klienci k ON z.id_klienta = k.id_klienta
JOIN Produkty p ON z.id_produktu = p.id_produktu
ORDER BY k.nazwisko;
Wynik pokazuje wszystkie zamówienia z nazwiskami klientów i kwotą zakupu.
b) Suma wydatków każdego klienta
SELECT k.imie, k.nazwisko,
SUM(z.ilosc * p.cena) AS suma_zamowien
FROM Klienci k
JOIN Zamowienia z ON k.id_klienta = z.id_klienta
JOIN Produkty p ON z.id_produktu = p.id_produktu
GROUP BY k.imie, k.nazwisko
ORDER BY suma_zamowien DESC;
Każdy klient pojawia się tylko raz – z łączną wartością swoich zakupów.
c) Średnia cena produktu w każdej kategorii
SELECT p.kategoria, AVG(p.cena) AS srednia_cena
FROM Produkty p
GROUP BY p.kategoria
HAVING AVG(p.cena) > 100
ORDER BY srednia_cena DESC;
Wynik pokazuje tylko te kategorie, w których średnia cena przekracza 100 zł.
d) Klienci, którzy złożyli więcej niż jedno zamówienie
SELECT k.imie, k.nazwisko, COUNT(z.id_zamowienia) AS liczba_zamowien
FROM Klienci k
JOIN Zamowienia z ON k.id_klienta = z.id_klienta
GROUP BY k.imie, k.nazwisko
HAVING COUNT(z.id_zamowienia) > 1
ORDER BY liczba_zamowien DESC;
Przydatne, by znaleźć „stałych klientów”.
e) Produkty, które zostały sprzedane przynajmniej raz
SELECT DISTINCT p.nazwa
FROM Produkty p
JOIN Zamowienia z ON p.id_produktu = z.id_produktu
ORDER BY p.nazwa;
f) Produkty, które nie zostały jeszcze zamówione
Tutaj przydaje się LEFT JOIN:
SELECT p.nazwa
FROM Produkty p
LEFT JOIN Zamowienia z ON p.id_produktu = z.id_produktu
WHERE z.id_produktu IS NULL;
Wynik pokaże produkty, które nie mają powiązania z żadnym zamówieniem.
g) Łączenie grupowania i sortowania
SELECT p.kategoria, COUNT(*) AS liczba_produktow, AVG(p.cena) AS srednia
FROM Produkty p
GROUP BY p.kategoria
ORDER BY srednia DESC;
Wynik: raport pokazujący, ile produktów jest w każdej kategorii i jaka jest ich średnia cena.
5. Kiedy używać WHERE, a kiedy HAVING?
To częste pytanie uczniów – oto proste wyjaśnienie:
| Klauzula | Działa na | Używana z | Przykład |
|---|---|---|---|
| WHERE | pojedyncze rekordy | zwykłe warunki | WHERE cena > 100 |
| HAVING | całe grupy | funkcje agregujące | HAVING SUM(cena) > 500 |
6. Typowe błędy w zapytaniach złożonych
- Brak GROUP BY przy funkcjach agregujących
→SELECT imie, SUM(cena)bezGROUP BY imiewywoła błąd. - Zamiana WHERE z HAVING
→HAVING cena > 100nie zadziała, bo HAVING działa tylko po grupowaniu. - Zły alias lub brak prefiksu tabeli
→ jeśli w zapytaniu są 2 tabele z kolumnąid, trzeba pisaćKlienci.id_klienta, nie samoid.
7. Zadania praktyczne
Zadanie 1 – analiza sprzedaży
- Wyświetl imię, nazwisko, nazwę produktu i wartość każdego zamówienia.
- Dodaj sortowanie malejąco po wartości zamówienia.
Zadanie 2 – raport klientów
- Wyświetl każdego klienta i sumę jego wszystkich zakupów.
- Pokaż tylko tych, którzy wydali więcej niż 500 zł.
- Posortuj wyniki malejąco po sumie zamówień.
Zadanie 3 – raport kategorii
- Dla każdej kategorii produktów oblicz:
- liczbę produktów,
- średnią cenę.
- Pokaż tylko te kategorie, w których średnia cena przekracza 100 zł.
- Posortuj wyniki malejąco po średniej.
Zadanie 4 – sprzedaż produktów
- Wyświetl listę produktów i liczbę zamówień, w których się pojawiły.
- Użyj
LEFT JOIN, by pokazać także produkty, których nikt jeszcze nie kupił. - Posortuj malejąco po liczbie zamówień.
Zadanie 5 – klienci i ilość produktów
- Wyświetl każdego klienta i łączną liczbę kupionych produktów (
SUM(ilosc)). - Użyj
GROUP BYiHAVING, by pokazać tylko klientów, którzy kupili więcej niż 2 produkty.
8. Podsumowanie
| Klauzula | Cel | Kolejność w zapytaniu |
|---|---|---|
| SELECT | wybór kolumn lub funkcji | 1 |
| FROM / JOIN | źródło danych i połączenia tabel | 2 |
| WHERE | filtrowanie rekordów | 3 |
| GROUP BY | grupowanie danych | 4 |
| HAVING | filtrowanie grup | 5 |
| ORDER BY | sortowanie wyników | 6 |
Zapytania złożone to sedno SQL — uczą logicznego myślenia o danych:
od pojedynczego rekordu, przez grupy, aż po końcowy raport.
To umiejętność, którą uczniowie wykorzystają w praktyce na egzaminie INF.03 i INF.04, oraz w każdej realnej pracy z bazami danych.

