Na poprzednim wykładzie pogadaliśmy o tym, jakie są typy JOIN w SQL. Dzisiaj skupimy się bardziej na INNER JOIN.
INNER JOIN — to taki rodzaj łączenia danych w relacyjnych bazach, który pozwala wziąć wiersze z dwóch tabel i zwrócić tylko te, które się "pokrywają" według warunku, który sam podasz. Czyli INNER JOIN zwraca tylko część wspólną dwóch tabel, całą resztę olewa.
Wyobraź sobie, że masz dwa pudełka. W jednym są kartki ze studentami, w drugim — kartki z kursami, na które studenci się zapisali. Chcesz się dowiedzieć, którzy studenci są zapisani na jakie kursy. Jeśli nie ma dopasowania (np. student nigdzie się nie zapisał), to na razie nas to nie obchodzi. Taki scenariusz to idealny przypadek dla INNER JOIN.
Składnia INNER JOIN
Składnia jest całkiem prosta — podajesz dwie tabele, które chcesz połączyć, i określasz warunek łączenia przez słowo kluczowe ON.
SELECT kolumny
FROM tabela1 INNER JOIN tabela2
ON tabela1.pole = tabela2.pole;
tabela1itabela2— to tabele, które chcesz połączyć.pole— to kolumny, po których następuje dopasowanie.- Warunek po
ONokreśla zasady dopasowania wierszy z obu tabel.
Przykłady użycia INNER JOIN
W dalszych przykładach będziemy pracować na dwóch tabelach:
Tabela students — dane o studentach
| student_id | name | age |
|---|---|---|
| 1 | Otto | 20 |
| 2 | Anna | 22 |
| 3 | Peter | 19 |
| 4 | Dia | 21 |
Tabela enrollments — dane o zapisach na kursy
| enrollment_id | student_id | course_id |
|---|---|---|
| 101 | 1 | 501 |
| 102 | 2 | 502 |
| 103 | 2 | 503 |
| 104 | 3 | 504 |
Zwróć uwagę, że studentka Dia (z student_id = 4) nie jest zapisana na żaden kurs.
Przykład 1: Pobieranie zapisów studentów i ich kursów
Chcemy się dowiedzieć, którzy studenci są zapisani na kursy. To typowy przypadek użycia INNER JOIN. Interesuje nas tylko to, gdzie są dopasowania między tabelami students i enrollments na podstawie student_id.
SELECT students.name, enrollments.course_id
FROM students INNER JOIN enrollments
ON students.student_id = enrollments.student_id;
Wynik:
| name | course_id |
|---|---|
| Otto | 501 |
| Anna | 502 |
| Anna | 503 |
| Peter | 504 |
Co widzimy? INNER JOIN zwrócił tylko tych studentów, którzy są zapisani na kursy. Studentka Dia, która nigdzie się nie zapisała, została pominięta.
Przykład 2: Pobieranie zamówień i klientów
Teraz zobaczmy inny przykład. Załóżmy, że mamy tabele orders (zamówienia) i customers (klienci). Chcemy dostać listę wszystkich zamówień z imionami klientów.
Tabela orders
| order_id | customer_id | amount |
|---|---|---|
| 1 | 101 | 500 |
| 2 | 102 | 300 |
| 3 | 103 | 700 |
Tabela customers
| customer_id | name |
|---|---|
| 101 | Otto |
| 102 | Anna |
| 104 | Peter |
Zadanie: musimy połączyć orders i customers po customer_id, żeby zwrócić tylko te zamówienia, które mają pasującego klienta.
SELECT orders.order_id, customers.name, orders.amount
FROM orders INNER JOIN customers
ON orders.customer_id = customers.customer_id;
Wynik:
| order_id | name | amount |
|---|---|---|
| 1 | Otto | 500 |
| 2 | Anna | 300 |
Zwróć uwagę, że zamówienie z order_id = 3 nie pojawiło się w wyniku, bo klient z customer_id = 103 nie istnieje w tabeli customers.
Jak INNER JOIN pomaga łączyć tabele (i co może pójść nie tak)
INNER JOIN — to podstawowe narzędzie, którego będziesz używać praktycznie w każdym projekcie z relacyjną bazą danych. To jak klucz płaski w skrzynce narzędziowej: możesz próbować bez niego, ale będzie ciężko osiągnąć efekt. Na przykład:
- Przy tworzeniu raportów, gdzie trzeba połączyć dane z kilku tabel.
- Do budowania analityki, kiedy trzeba połączyć fakty z wymiarami (np. sprzedaż i klienci).
- Do integracji danych z zewnętrznych systemów.
Najczęstszy błąd początkujących to zapomniane ON albo źle podany warunek łączenia. Jeśli nie ustawisz poprawnego warunku, zamiast oczekiwanego wyniku dostaniesz iloczyn kartezjański dwóch tabel — to może być tysiące albo miliony wierszy, które nie mają sensu.
Przykład błędu:
W tym przykładzie nie ma warunku łączenia, więc zapytanie stworzy każdą możliwą kombinację wierszy z dwóch tabel (i to raczej nie to, czego chcesz):
SELECT students.name, enrollments.course_id
FROM students, enrollments; -- BŁĄD: brak warunku łączenia!
Wynik będzie wyglądał jak chaos: każdy wiersz z students zostanie połączony z każdym wierszem z enrollments.
GO TO FULL VERSION