INF.03 · Bazy danych i SQL

JOIN: jak połączyć dane z kilku tabel w jedną odpowiedź

W zamówieniu zapisano numery: klient 1 kupił produkt 4. Nikt nie chce raportu „1 kupił 4”. Chcemy przeczytać: „Jan Kowalski kupił kostkę gitarową”. JOIN zamienia numery na zrozumiałe dane, a warunek ON mówi bazie, które wiersze pasują do siebie.

  • około 35 minut
  • INNER JOIN i LEFT JOIN
  • bazy: szkola_relacje, sklep_muzyczny

Po tej lekcji: znajdziesz parę kluczy do połączenia, napiszesz INNER JOIN i LEFT JOIN z aliasami, połączysz trzy tabele i sprawdzisz, czy liczba wierszy wyniku jest sensowna.

1 · Co z czym łączyć

Warunek ON to nie zgadywanka

Umiesz już zbudować zapytanie SELECT → FROM → WHERE → ORDER BY → LIMIT. JOIN rozszerza część FROM: wskazuje kolejną tabelę i warunek dopasowania wierszy. Warunek budujesz z pary kluczy: klucza obcego i odpowiadającego mu klucza głównego.

TabelaKluczRola
Klienciid_klientaklucz główny: rozpoznaje klienta
Zamowieniaid_klientaklucz obcy: wskazuje klienta zamówienia
Produktyid_produktuklucz główny: rozpoznaje produkt
Zamowieniaid_produktuklucz obcy: wskazuje zamówiony produkt
Baza sklep_muzyczny. Po lewej tabela, po środku kolumna, po prawej jej rola.
SQLsql
FROM Zamowienia AS z
INNER JOIN Klienci AS k
    ON z.id_klienta = k.id_klienta
  1. Aliasy z i k skracają zapis, a przy kolumnach pozwalają zawsze wskazać, z której tabeli pochodzą.
  2. ON łączy klucz obcy z.id_klienta z kluczem głównym k.id_klienta.

Laboratorium · ćwiczenie w przeglądarce, do którego odsyłają rozgrzewki na końcu lekcji

2 · Sprawdź na danych

Rodzaj złączenia i warunek ON: co zmieniają?

Prawdziwe dane z bazy szkola_relacje: pięć przedmiotów i dwanaście zapisów uczniów. Jeden przedmiot (angielski zawodowy) nie ma żadnego zapisu. Zmieniaj rodzaj złączenia i warunek, a potem patrz, ile wierszy dostajesz i co się stało z przedmiotem bez uczniów.

Ta interakcja wymaga włączonego JavaScriptu.

Zwróć uwagę na pułapkę: INNER JOIN po cichu pomija przedmiot bez uczniów. Jeśli chcesz zobaczyć wszystkie przedmioty, także puste, potrzebujesz LEFT JOIN z tabelą „wszystkich” po lewej stronie.

3 · Pełny raport

Jan Kowalski kupił kostkę gitarową

Zamówienie zapisuje tylko numery klienta i produktu. Zaczynamy więc od tabeli Zamowienia, a dwa kolejne JOIN zamieniają numery na imię, nazwisko i nazwę produktu.

raport.sqlsql
SELECT z.id_zamowienia, k.imie, k.nazwisko,
       p.nazwa AS produkt, z.ilosc
FROM Zamowienia AS z
INNER JOIN Klienci AS k ON z.id_klienta = k.id_klienta
INNER JOIN Produkty AS p ON z.id_produktu = p.id_produktu
ORDER BY z.id_zamowienia
LIMIT 5;
  1. Pierwszy ON dobiera właściciela zamówienia, drugi dobiera zamówiony produkt.
  2. p.nazwa AS produkt nadaje kolumnie czytelny nagłówek w wyniku.
  3. Kontrola liczby wierszy. Połączenie trzech tabel bez LIMIT zwraca 15 wierszy, czyli tyle, ile jest zamówień. Inna liczba oznacza błąd w warunkach ON.
id_zamowieniaimienazwiskoproduktilosc
1JanKowalskiGitara elektryczna1
2JanKowalskiKostka gitarowa10
3AnnaNowakKolumna aktywna1
4MarekWisniewskiStruny do gitary2
5EwaZielinskaMikrofon dynamiczny1
Wynik: pierwsze 5 z 15 wierszy.

4 · Zanim się pomylisz

Cztery pomyłki w JOIN

Rozwiń każdą z nich. Liczby pochodzą z bazy sklep_muzyczny (15 zamówień i 8 klientów).

Brak warunku ON
Tak nie
SELECT z.id_zamowienia, k.imie
FROM Zamowienia AS z
JOIN Klienci AS k;

Każde z 15 zamówień łączy się z każdym z 8 klientów: 120 wierszy zamiast 15. Wynik wygląda poprawnie, ale jest bezsensowny.

Tak
SELECT z.id_zamowienia, k.imie
FROM Zamowienia AS z
JOIN Klienci AS k ON z.id_klienta = k.id_klienta;

Zawsze porównaj liczbę wierszy wyniku z liczbą zamówień.

Niejednoznaczna nazwa kolumny
Tak nie
SELECT id_klienta, imie
FROM Zamowienia AS z
JOIN Klienci AS k ON z.id_klienta = k.id_klienta;

Błąd: Column 'id_klienta' in field list is ambiguous. Obie tabele mają taką kolumnę.

Tak
SELECT k.id_klienta, k.imie
FROM Zamowienia AS z
JOIN Klienci AS k ON z.id_klienta = k.id_klienta;

Poprzedź nazwę aliasem tabeli: k.id_klienta.

Zły kierunek LEFT JOIN
Tak nie
SELECT k.imie, z.id_zamowienia
FROM Zamowienia AS z
LEFT JOIN Klienci AS k ON z.id_klienta = k.id_klienta;

Zachowasz wszystkie zamówienia, ale klient bez zamówień się nie pojawi. Zachowywana jest tabela po lewej stronie zapisu.

Tak
SELECT k.imie, z.id_zamowienia
FROM Klienci AS k
LEFT JOIN Zamowienia AS z ON z.id_klienta = k.id_klienta;

Chcesz wszystkich klientów, więc tabela Klienci musi stać po lewej.

WHERE przed JOIN
Tak nie
SELECT z.id_zamowienia
FROM Zamowienia AS z
WHERE z.ilosc > 1
JOIN Klienci AS k ON z.id_klienta = k.id_klienta;

Błąd składni: You have an error in your SQL syntax. Baza oczekuje stałej kolejności.

Tak
SELECT z.id_zamowienia
FROM Zamowienia AS z
JOIN Klienci AS k ON z.id_klienta = k.id_klienta
WHERE z.ilosc > 1;

Najpierw wszystkie JOIN, potem WHERE, na końcu ORDER BY.

5 · Sprawdź sam siebie

Zanim uznasz JOIN za poprawny

Na egzaminie sprawdzaj pary kluczy, aliasy, warunki ON i liczbę rekordów. Czytelny wynik pokazuje nazwy i opisy, a nie same obce identyfikatory.

Podsumowanie

Co warto zapamiętać

  1. JOIN rozszerza część FROM. Warunek ON łączy klucz obcy z kluczem głównym.
  2. INNER JOIN zostawia tylko pary dopasowane, a LEFT JOIN zachowuje wszystkie wiersze tabeli po lewej (brak pary to NULL).
  3. Aliasy skracają zapis i rozstrzygają, z której tabeli pochodzi kolumna.
  4. Brak ON daje iloczyn kartezjański: każdy wiersz z każdym.
  5. Po każdym JOIN porównaj liczbę wierszy z oczekiwaną.

Dalej na swoim koncie

Rozgrzewki, quiz i zadania są w biurku ucznia.

Teoria jest otwarta dla wszystkich. Żeby rozwiązywać zadania, zapisywać szkice i widzieć swój postęp, zaloguj się.

Zaloguj się →
Źródła i dalsza nauka