Relacje i łączenie tabel w SQL

Wyobraź sobie sklep muzyczny.
Masz trzy półki:

  • na jednej są klienci,
  • na drugiej produkty,
  • a na trzeciej zamówienia.

Każda półka (czyli tabela) zawiera inne informacje, ale wszystkie są ze sobą powiązane.
Żeby dowiedzieć się, kto co kupił, musimy połączyć dane z kilku tabel.
Na tym właśnie polegają relacje i łączenie tabel (JOIN).


1. Czym są relacje w bazie danych?

Relacje pokazują, jak tabele są ze sobą powiązane.
To tak, jakbyś miał trzy kartoteki połączone nitkami — klienta, produkt i zamówienie.

W relacyjnej bazie danych tabele łączą się ze sobą za pomocą kluczy:

  • klucz główny (PRIMARY KEY) – jednoznacznie identyfikuje każdy rekord,
  • klucz obcy (FOREIGN KEY) – wskazuje na rekord w innej tabeli.

2. Przykład – baza sklep_muzyczny

W naszym przykładzie mamy trzy tabele:

CREATE DATABASE sklep_muzyczny;
USE sklep_muzyczny;

Tabela Klienci

CREATE TABLE Klienci (
    id_klienta INT AUTO_INCREMENT PRIMARY KEY,
    imie VARCHAR(50) NOT NULL,
    nazwisko VARCHAR(50) NOT NULL,
    email VARCHAR(100) NOT NULL UNIQUE
);

Tabela Produkty

CREATE TABLE Produkty (
    id_produktu INT AUTO_INCREMENT PRIMARY KEY,
    nazwa VARCHAR(100) NOT NULL,
    cena DECIMAL(10, 2) NOT NULL,
    kategoria VARCHAR(50) NOT NULL
);

Tabela Zamowienia

CREATE TABLE Zamowienia (
    id_zamowienia INT AUTO_INCREMENT PRIMARY KEY,
    id_klienta INT NOT NULL,
    id_produktu INT NOT NULL,
    ilosc INT NOT NULL,
    data_zamowienia DATE NOT NULL,
    FOREIGN KEY (id_klienta) REFERENCES Klienci(id_klienta),
    FOREIGN KEY (id_produktu) REFERENCES Produkty(id_produktu)
);

Zauważ, że tabela Zamowienia łączy klientów i produkty przez klucze obce (FOREIGN KEY).
Każde zamówienie mówi nam, który klient kupił jaki produkt i kiedy.


3. Wstawianie przykładowych danych

-- Klienci
INSERT INTO Klienci (imie, nazwisko, email) VALUES
('Jan', 'Kowalski', 'jan.kowalski@example.com'),
('Anna', 'Nowak', 'anna.nowak@example.com'),
('Marek', 'Wiśniewski', 'marek.wisniewski@example.com');

-- Produkty
INSERT INTO Produkty (nazwa, cena, kategoria) VALUES
('Gitara akustyczna', 499.99, 'Instrumenty'),
('Keyboard Yamaha', 1299.99, 'Instrumenty'),
('Mikrofon Shure', 299.99, 'Akcesoria'),
('Słuchawki Sony', 199.99, 'Akcesoria'),
('Struny do gitary', 39.99, 'Akcesoria');

-- Zamówienia
INSERT INTO Zamowienia (id_klienta, id_produktu, ilosc, data_zamowienia) VALUES
(1, 1, 1, '2025-01-01'),
(1, 5, 2, '2025-01-01'),
(2, 2, 1, '2025-01-02'),
(2, 4, 1, '2025-01-02'),
(3, 3, 1, '2025-01-03');

4. Typy relacji

W bazach danych wyróżniamy trzy główne typy relacji:

Typ relacjiOpisPrzykład
1:1 (jeden do jednego)jeden rekord w tabeli A odpowiada jednemu w tabeli Bnp. pracowniklegitymacja
1:N (jeden do wielu)jeden rekord w tabeli A może mieć wiele powiązanych rekordów w tabeli Bklientzamówienia
N:M (wiele do wielu)wiele rekordów w tabeli A może mieć wiele powiązań w tabeli Buczniowieprzedmioty (z tabelą pośredniczącą oceny)

W naszym sklepie występuje relacja 1:N:

  • jeden klient może złożyć wiele zamówień,
  • ale jedno zamówienie należy do jednego klienta.

5. Łączenie tabel – JOIN

Aby wyświetlić dane z kilku tabel naraz, używamy JOIN.
To polecenie pozwala połączyć tabele po wspólnych kolumnach.


a) INNER JOIN – dane, które występują w obu tabelach

Pokaż, kto co kupił:

SELECT Klienci.imie, Klienci.nazwisko, Produkty.nazwa, Zamowienia.ilosc
FROM Zamowienia
INNER JOIN Klienci ON Zamowienia.id_klienta = Klienci.id_klienta
INNER JOIN Produkty ON Zamowienia.id_produktu = Produkty.id_produktu;

Wynik:

imienazwiskonazwailosc
JanKowalskiGitara akustyczna1
JanKowalskiStruny do gitary2
AnnaNowakKeyboard Yamaha1
AnnaNowakSłuchawki Sony1
MarekWiśniewskiMikrofon Shure1

b) LEFT JOIN – wszystkie rekordy z lewej tabeli (nawet jeśli nie mają dopasowania)

Pokaż wszystkich klientów, nawet tych, którzy nie złożyli żadnego zamówienia:

SELECT Klienci.imie, Klienci.nazwisko, Produkty.nazwa
FROM Klienci
LEFT JOIN Zamowienia ON Klienci.id_klienta = Zamowienia.id_klienta
LEFT JOIN Produkty ON Zamowienia.id_produktu = Produkty.id_produktu;

Jeśli jakiś klient nic nie kupił, kolumna nazwa będzie pusta (NULL).


c) RIGHT JOIN – wszystkie rekordy z prawej tabeli

Pokaż wszystkie produkty, nawet jeśli nikt ich nie kupił:

SELECT Produkty.nazwa, Produkty.cena, Klienci.imie, Klienci.nazwisko
FROM Produkty
RIGHT JOIN Zamowienia ON Produkty.id_produktu = Zamowienia.id_produktu
RIGHT JOIN Klienci ON Zamowienia.id_klienta = Klienci.id_klienta;

d) CROSS JOIN – połączenie wszystkich rekordów z obu tabel (uwaga!)

Rzadko używane – tworzy każdą możliwą kombinację:

SELECT Klienci.imie, Produkty.nazwa
FROM Klienci
CROSS JOIN Produkty;

Jeśli jest 3 klientów i 5 produktów, wynik da 15 wierszy.


6. Aliasowanie tabel

Żeby zapytania były krótsze i czytelniejsze, można nadać tabelom aliasy:

SELECT k.imie, k.nazwisko, p.nazwa, z.ilosc
FROM Zamowienia z
JOIN Klienci k ON z.id_klienta = k.id_klienta
JOIN Produkty p ON z.id_produktu = p.id_produktu;

7. Zadania praktyczne

Zadanie 1 – proste połączenie

Wyświetl listę wszystkich klientów i produkty, które kupili (imie, nazwisko, nazwa produktu, data zamówienia).


Zadanie 2 – brak zamówień

Używając LEFT JOIN, pokaż wszystkich klientów, nawet tych, którzy nie złożyli żadnego zamówienia.
Dla takich klientów kolumna nazwa powinna mieć wartość NULL.


Zadanie 3 – najdroższe zakupy

Wyświetl klientów i produkty posortowane malejąco po cenie produktu (ORDER BY cena DESC).


Zadanie 4 – zliczanie zamówień (dla chętnych)

Pokaż każdego klienta i liczbę jego zamówień:

SELECT k.imie, k.nazwisko, COUNT(z.id_zamowienia) AS liczba_zamowien
FROM Klienci k
LEFT JOIN Zamowienia z ON k.id_klienta = z.id_klienta
GROUP BY k.imie, k.nazwisko;

Podsumowanie

Typ relacji / JOINCo robiKiedy używać
INNER JOINzwraca tylko powiązane rekordygdy interesują nas tylko dopasowania
LEFT JOINzwraca wszystkie rekordy z lewej tabeligdy chcemy zobaczyć również brakujące dane
RIGHT JOINzwraca wszystkie rekordy z prawej tabelirzadziej używany, działa jak LEFT w drugą stronę
CROSS JOINtworzy każdą możliwą kombinacjęgłównie do testów lub specjalnych analiz
FOREIGN KEYłączy dane między tabelamizapewnia spójność i integralność danych

Relacje i łączenie tabel to serce relacyjnych baz danych.
Dzięki nim możesz łączyć różne informacje i uzyskać pełny obraz danych – kto kupił, co kupił i kiedy.
Bez tego SQL byłby tylko zbiorem osobnych tabel, a nie prawdziwym systemem informacji.