Zapytania złożone w SQL

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:

  1. pobieramy dane z kilku tabel (JOIN),
  2. grupujemy je (GROUP BY),
  3. wykonujemy obliczenia (SUM, COUNT, AVG),
  4. filtrujemy wyniki (HAVING, WHERE),
  5. 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:

KlauzulaDziała naUżywana zPrzykład
WHEREpojedyncze rekordyzwykłe warunkiWHERE cena > 100
HAVINGcałe grupyfunkcje agregująceHAVING SUM(cena) > 500

6. Typowe błędy w zapytaniach złożonych

  1. Brak GROUP BY przy funkcjach agregujących
    SELECT imie, SUM(cena) bez GROUP BY imie wywoła błąd.
  2. Zamiana WHERE z HAVING
    HAVING cena > 100 nie zadziała, bo HAVING działa tylko po grupowaniu.
  3. Zły alias lub brak prefiksu tabeli
    → jeśli w zapytaniu są 2 tabele z kolumną id, trzeba pisać Klienci.id_klienta, nie samo id.

7. Zadania praktyczne

Zadanie 1 – analiza sprzedaży

  1. Wyświetl imię, nazwisko, nazwę produktu i wartość każdego zamówienia.
  2. Dodaj sortowanie malejąco po wartości zamówienia.

Zadanie 2 – raport klientów

  1. Wyświetl każdego klienta i sumę jego wszystkich zakupów.
  2. Pokaż tylko tych, którzy wydali więcej niż 500 zł.
  3. Posortuj wyniki malejąco po sumie zamówień.

Zadanie 3 – raport kategorii

  1. Dla każdej kategorii produktów oblicz:
    • liczbę produktów,
    • średnią cenę.
  2. Pokaż tylko te kategorie, w których średnia cena przekracza 100 zł.
  3. Posortuj wyniki malejąco po średniej.

Zadanie 4 – sprzedaż produktów

  1. Wyświetl listę produktów i liczbę zamówień, w których się pojawiły.
  2. Użyj LEFT JOIN, by pokazać także produkty, których nikt jeszcze nie kupił.
  3. Posortuj malejąco po liczbie zamówień.

Zadanie 5 – klienci i ilość produktów

  1. Wyświetl każdego klienta i łączną liczbę kupionych produktów (SUM(ilosc)).
  2. Użyj GROUP BY i HAVING, by pokazać tylko klientów, którzy kupili więcej niż 2 produkty.

8. Podsumowanie

KlauzulaCelKolejność w zapytaniu
SELECTwybór kolumn lub funkcji1
FROM / JOINźródło danych i połączenia tabel2
WHEREfiltrowanie rekordów3
GROUP BYgrupowanie danych4
HAVINGfiltrowanie grup5
ORDER BYsortowanie wyników6

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.