Zadanie 5: Sklep komputerowy — relacje i zapytania JOIN
ŚredniPo co się tego uczymy?
Do tej pory Klienci i Produkty istniały niezależnie od siebie. Teraz połączysz je piątą tabelą — Zamówienia — i nauczysz się odpowiadać na pytania, które wymagają danych z kilku tabel naraz.
Treść zadania
Scenariusz: Do tej pory Klienci i Produkty istniały niezależnie od siebie — nikt jeszcze niczego nie kupił. Teraz połączysz je piątą tabelą, Zamowienia, i nauczysz się odpowiadać na pytania, które wymagają danych z kilku tabel naraz.
Do wykonania:
1. Dodaj piątą tabelę Zamowienia z kluczami obcymi do Klienci i Produkty, kolumnami ilość i data zamówienia.
2. Wypełnij ją co najmniej 15 przykładowymi zamówieniami.
3. Napisz zapytanie pokazujące imię, nazwisko klienta oraz nazwę produktu i ilość dla każdego zamówienia.
4. Napisz zapytanie pokazujące łączną kwotę wydaną przez każdego klienta.
5. Znajdź produkty, które nigdy nie zostały zamówione.
6. Znajdź klienta, który wydał najwięcej pieniędzy w sklepie.
7. Pokaż wszystkich klientów razem z liczbą złożonych zamówień — również tych, którzy jeszcze nic nie zamówili.
Schemat
Kategorie 1 ──── * Produkty Producenci 1 ──── * Produkty Klienci 1 ──── * Zamowienia Produkty 1 ──── * Zamowienia
Jak zabrać się do zadania
1. Najpierw wykonaj krok 1 (dodanie i wypełnienie tabeli Zamowienia) — bez tego żadne z zapytań JOIN nie zadziała.
2. Sprawdź SELECT * FROM Zamowienia; i upewnij się, że dane faktycznie tam są, zanim napiszesz pierwszy JOIN.
3. Buduj złączenia stopniowo: najpierw połącz tylko dwie tabele i sprawdź wynik, dopiero potem dołóż trzecią.
4. W zapytaniach z LEFT JOIN (punkty 3 i 5) pamiętaj o warunku IS NULL, żeby wyłuskać "brakujące" dopasowania.
Jak powinien wyglądać efekt
Zapytanie 5 (produkty nigdy niezamówione) powinno pokazać kilka, ale nie wszystkie produkty:
+---------------------------+ | nazwa | +---------------------------+ | Monitor 32" 4K | | Pamięć RAM 64GB DDR5 | +---------------------------+ 2 rows in set (0.00 sec)
Jeśli zamiast tego dostajesz pusty wynik (Empty set), prawdopodobnie użyłeś INNER JOIN zamiast LEFT JOIN — INNER JOIN "gubi" właśnie te niedopasowane wiersze, których szukasz.
Typowe problemy i jak sobie z nimi poradzić
INNER JOIN zamiast LEFT JOIN. Co się stało: zapytania 5 i 7 zwracają puste albo niepełne wyniki. Dlaczego: INNER JOIN pokazuje tylko wiersze z dopasowaniem w OBU tabelach — "gubi" produkty bez zamówień i klientów bez zamówień. Jak naprawić: zamień na LEFT JOIN, żeby zachować też te "osierocone" rekordy.
Zapomniany warunek ON. Co się stało: zapytanie z JOIN zwraca setki albo tysiące wierszy zamiast kilkunastu. Dlaczego: brak warunku ON powoduje iloczyn kartezjański — każdy wiersz z jednej tabeli łączy się z każdym wierszem drugiej. Jak naprawić: zawsze dopisuj ON tabela1.klucz = tabela2.klucz po każdym JOIN.
Klucz obcy do nieistniejącego klienta lub produktu. Co się stało: INSERT INTO Zamowienia zgłasza błąd ograniczenia klucza obcego. Dlaczego: id_klienta albo id_produktu, które podałeś, nie istnieje w odpowiedniej tabeli. Jak naprawić: sprawdź SELECT * FROM Klienci; i SELECT * FROM Produkty;, żeby użyć prawdziwych identyfikatorów.
Nawiązanie do egzaminu zawodowego
To połączenie efektów INF.03.4.2 (relacje) i INF.03.4.4 (SQL) w jednym praktycznym ćwiczeniu — dokładnie taki typ zadania (dane rozproszone po kilku powiązanych tabelach) dominuje w części praktycznej egzaminu.
Kryteria sukcesu — sprawdź, czy wykonałeś zadanie poprawnie
Po wykonaniu zadania sprawdź, czy:
1. tabela Zamowienia ma co najmniej 15 wierszy,
2. zapytanie 3 (JOIN trzech tabel) nie zwraca błędów i pokazuje sensowne imiona/nazwy produktów, a nie same liczby id,
3. zapytanie 5 używa LEFT JOIN, a nie INNER JOIN (inaczej nic nie zwróci),
4. zapytanie 7 pokazuje WSZYSTKICH klientów, nawet tych z liczbą zamówień równą 0,
5. suma z zapytania 4 dla każdego klienta zgadza się (choćby w przybliżeniu) z tym, ile zamówień faktycznie mu przypisałeś.
Rozwiązanie — zajrzyj tu dopiero na końcu
To jest rozwiązanie wzorcowe. Zajrzyj tu dopiero wtedy, gdy samodzielnie spróbujesz wykonać zadanie. Nie kopiuj kodu bezmyślnie — przepisanie go ręcznie pomaga zapamiętać składnię i kolejność działań. Kod jest celowo zablokowany do kopiowania.
CREATE TABLE Zamowienia (
id_zamowienia INT AUTO_INCREMENT PRIMARY KEY,
id_klienta INT NOT NULL,
id_produktu INT NOT NULL,
ilosc INT NOT NULL DEFAULT 1,
data_zamowienia DATE NOT NULL,
FOREIGN KEY (id_klienta) REFERENCES Klienci(id_klienta),
FOREIGN KEY (id_produktu) REFERENCES Produkty(id_produktu)
);
INSERT INTO Zamowienia (id_klienta, id_produktu, ilosc, data_zamowienia) VALUES
(1, 1, 1, '2026-01-05'),
(1, 5, 2, '2026-01-05'),
(2, 3, 1, '2026-01-10'),
(3, 7, 1, '2026-01-12'),
(3, 9, 1, '2026-01-12'),
(4, 2, 1, '2026-01-15'),
(5, 6, 3, '2026-01-18'),
(6, 10, 1, '2026-01-20'),
(1, 4, 1, '2026-01-22'),
(7, 8, 2, '2026-01-25'),
(2, 11, 1, '2026-01-28'),
(8, 12, 1, '2026-02-01'),
(3, 13, 1, '2026-02-03'),
(5, 14, 4, '2026-02-05'),
(6, 15, 1, '2026-02-08');