Kurs SQL #07: Łączenie wielu tabel i typy złączeń

Przedstawiłem już ogólną koncepcje tworzenia łączeń w języku SQL. Wykonaliśmy też proste złączenia dwóch tabel. Tym razem Darmowy Kurs SQL zostaje rozszerzony o metody na pobieranie przy pomocy instrukcji SELECT danych z wielu tabel na raz.

Zaczynasz Darmowym Kurs SQL? Pierwsza część dostępna tutaj: Kurs SQL #01: Wprowadzenie i środowisko

eBook Niezbędnik Administratora Baz Danych cover

Instrukcja SELECT i wiele tabel

W większości przypadków kiedy korzystamy z bazy danych pobieramy dane z wielu tabel. Dzisiejszy złożony świat przekłada się na rozbudowane relacje w bazach. Stosunkowo rzadko jest potrzeba pobrania informacji z pojedynczej tabeli. Wynika to choćby z wspomnianego już wcześniej w Darmowym Kursie SQL dążenia do ograniczenia duplikacji danych w bazie.

Nie istnieje żadne ograniczenie co do ilości tabel mogących brać udział w złączeniach. Zawsze liczba złączeń w zapytaniu będzie o jeden mniejsza od ilości tabel w nim biorących.

Typy złączeń

Złączenia wewnętrzne – INNER JOIN

Ten typ złączenia wykorzystywaliśmy już w naszych zapytaniach. Rzuć zatem okiem jak wygląda takie złączenie w nieco bardziej rozbudowanym zapytaniu. W przykładach nie stosuje aliasów, dla łatwiejszego zrozumienia zapytań 😉

select 
    oe.customers.cust_first_name, 
    oe.customers.cust_last_name, 
    oe.orders.order_mode, 
    oe.order_items.quantity, 
    oe.product_information.list_price
from oe.customers, oe.orders, oe.order_items, oe.product_information
where customers.customer_id = orders.customer_id
and oe.orders.order_id = oe.order_items.order_id
and oe.order_items.product_id= oe.product_information.product_id;
CUST_FIRST_NAMECUST_LAST_NAMEORDER_MODEQUANTITYLIST_PRICE
HarrisonSutherlanddirect5316
HarrisonSutherlanddirect4781
HarrisonSutherlanddirect4746
HarrisonSutherlanddirect4821

Powyższy przykład wykorzystuje cztery tabele: CUSTOMERS, ORDERS, ORDER_ITEMS i PRODUCT_INFORMATION. Jak się pewnie domyślasz mamy w nich informacje o klientach, zamówieniach, produktach które w tych zamówieniach są i o samych produktach dostępnych w sklepie.

Równozłączenia wykonane w zapytaniu:

  • CLIENTS i ORDERS po kluczach CUSTOMER_ID
  • ORDERS i ORDER_ITEMS po kluczach ORDER_ID
  • ORDER_ITEMS I PRODUCT_INFORMATION po kluczach PRODUCT_ID

Jak widzisz mamy cztery tabele biorące udział w zapytaniu, co przekłada się na trzy złączenia. Wyświetlane są tylko te wiersze, które mają dopasowanie po drugiej stronie danego złączenia. W wynikach nie zobaczysz produktów które nigdy nie była zamawiane, czy użytkowników sklepu którzy nigdy nic nie zamówili.


Zostań Administratorem Baz Danych! 

Kompleksowy kurs z moim wsparciem: Praktyczna Administracja Oracle Database!


Złączenia zewnętrzne – OUTER JOIN

Złączenie tego typu wyświetla dany wiersz nawet, jeżeli nie ma dla niego dopasowania po drugiej stronie złączenia. Baza danych Oracle jako operator tego typu złączeń wykorzystuje znak plus w nawiasach (+).

select 
    oe.order_items.order_id,
    oe.product_information.product_name
from oe.order_items, oe.product_information 
where oe.order_items.product_id (+) = oe.product_information.product_id 
order by 1 desc;
ORDER_IDPRODUCT_NAME
HD 6GB /I
Chemicals – RCP
SPNIX3.3 C/DU
C for SPNIX3.3 – Seat/U

Nieco uprościłem nasze zapytanie. Skupmy się na części gdzie tabela z spisem zamówień łączy się z tabelą informacji o produktach. Czy każde zamówienie musi mieć odwołanie do jakiegoś produktu? Zdecydowanie tak 😉 Czy każdy produkt w sklepie musi mieć odwołanie do jakiegoś zamówienia? Oczywiście nie! Przecież w sklepie mogą być produkty, których nikt nigdy nie kupił.

Gdy nie użyjemy operatora (+) baza danych zwróci listę zamówień z przyporządkowanymi do nich produktami. Produkty nigdy nie zamawiane nie pojawią się w wyniku zapytania. Poprzez zastosowanie operatora (+) poinstruowaliśmy bazę danych o chęci wyświetlenia kompletu produktów, nawet jeśli nie ma dla nich przyporządkowanego zamówienia.

Klauzule ORDER BY dodałem tylko po to, aby wyświetlić nasze NULL’e na górze wyników zapytania. Warto zapamiętać, że w bazie danych Oracle NULL traktowany jest jako wartość większa od jakiejkolwiek wartości znanej. Dlatego też wykonałem sortowanie malejące 😉 Miej na uwadze, że traktowanie NULL jako wartość największa lub najmniejsza jest zależne od silnika bazy danych.

Operator (+) stawiasz zawsze po przeciwnej stronie niż tabela z której chcesz pozyskać komplet wierszy 😉

kurs sql złączenia typy inner outer join
Typy złączeń

Złączenie własne

Kolejny typ złączeń to złączenia wewnętrze. Tutaj z kolei robimy coś nietypowego na pierwszy rzut oka. Łączymy tabele z nią samą 😉 Zastanawiasz się zapewne w jakim celu mamy robić coś takiego. Najlepszy do zobrazowania zagadnienia będzie koronny i stary jak świat przykład spisu pracowników.

SELECT w.first_name || ' ' || w.last_name || ' jest podwładnym ' || m.first_name || ' ' || m.last_name
FROM hr.employees w, hr.employees m 
WHERE w.manager_id = m.employee_id 
ORDER BY w.first_name;

W.FIRST_NAME||”||W.LAST_NAME||’JESTPODWŁADNYM’||M.FIRST_NAME||”||M.LAST_NAME
Adam Fripp jest podwładnym Steven King
Alana Walsh jest podwładnym Kevin Mourgos
Alberto Errazuriz jest podwładnym Steven King
Alexander Khoo jest podwładnym Den Raphaely

Jak widzisz skorzystałem z tabeli EMPLOYEES w schemacie HR. W przypadku tego typu złączenia należy zastosować aliasy w celu rozróżnienia tabel. W klauzuli FROM wymieniłem tabele EMPOYEES dwa razy, każdorazowo nadając jej oddzielny alias. Praktycznie każda osoba w firmie ma swojego przełożonego. Każdy pracownik ma w kolumnie MANAGER_ID EMPLOYEE_ID swojego szefa 😉

Złączeniem tym przyporządkowałem każdemu wierszowi opisującemu pracownika, wiersz z tej samej tabeli opisujący jego przełożonego 🙂

W kolejnej części Darmowego Kursu SQL przyjrzymy się nieco nowszej składni SQL/92.


Część ósma kursu dostępna! Kurs SQL #08: Łączenia w składni SQL/92