TOP

Lekcja SQL 11. Zaawansowana kombinacja tabel (OUTER JOIN)

W poprzedniej sekcji rozważaliśmy najprostsze sposoby łączenia tabel - używając zdań WHERE i INNER JOIN. Kombinacje te nazywane są kombinacjami wewnętrznymi lub kombinacjami równoważności. Jednak SQL ma w swoim arsenale znacznie więcej opcji łączenia tabel, a mianowicie istnieją również inne typy złączeń: złączenia zewnętrzne, złączenia naturalne i złączenia samoczynne. Najpierw jednak zastanówmy się, w jaki sposób możemy przypisać aliasy do tabel, gdyż później będziemy zmuszeni używać pełnych nazw pól (Table.Field), które bez skrótów będą bardzo trudne w obsłudze ze względu na ich dużą długość.


1. Używanie aliasów tabel (Aliasy)

W poprzedniej sekcji dowiedzieliśmy się, jak można używać aliasów w odniesieniu do określonych pól tabeli lub pól obliczeniowych. SQL pozwala nam również używać aliasów zamiast nazw tabel. Daje nam to takie korzyści, jak krótsza składnia SQL i pozwala nam wielokrotnie używać tej samej tabeli w instrukcji SELECT.

Run SQLSELECT Seller_name, SUM(Amount) AS Sum1 
FROM Sellers AS S, Sumproduct AS SP 
WHERE S.City = SP.City 
GROUP BY Seller_name

Dla każdego sprzedającego wyświetliliśmy łączną kwotę sprzedanych towarów. W naszym zapytaniu SQL użyliśmy następujących aliasów: dla pola obliczeniowego SUM(Amount) alias Sum1, dla tabeli Sellers alias S oraz dla Sumproduct alias SP. Pamiętaj, że aliasy tabel mogą być również używane w innych zdaniach, takich jak ORDER BY, GROUP BY i innych.

2. Samopołączenie (SELF JOIN)

Rozważmy przykład. Załóżmy, że musimy znać adresy sprzedawców prowadzących działalność w tym samym kraju co John Smith. W tym celu utworzymy następujące żądanie:

Run SQLSELECT Address, City, Country, Seller_name
FROM Sellers
WHERE Country = (SELECT Country 
                 FROM Sellers 
                 WHERE Seller_name = 'John Smith')

Możemy również rozwiązać ten problem poprzez samodzielne połączenie, pisząc następujący kod:

Run SQLSELECT S1.Address, S1.City, S1.Country, S1.Seller_name
FROM Sellers AS S1, Sellers AS S2 
WHERE S1.Country = S2.Country AND S2.Seller_name = 'John Smith'

Aby rozwiązać ten problem, zastosowano pseudonimy. Za pierwszym razem tabeli Sellers przypisano alias S1, za drugim razem alias S2. Aliasy te można następnie wykorzystać jako nazwy tabel. W operatorze WHERE do nazwy każdego pola dodajemy przedrostek S1, aby system DBMS zrozumiał, jakie pola ma wyprowadzić tabela (ponieważ z jednej tabeli utworzyliśmy dwie wirtualne tabele). Klauzula WHERE najpierw łączy tabele, a następnie filtruje dane drugiej tabeli według pola Seller_name, aby zwrócić tylko niezbędne wartości.

Samosprzężenia są często używane do zastępowania podzapytań, które wybierają dane z tej samej tabeli, co operator zewnętrzny SELECT. Chociaż wynik końcowy jest taki sam, wiele procesów DBMS łączy się znacznie szybciej niż podzapytania. Warto poeksperymentować, aby określić, które zapytanie działa szybciej.

3. Naturalne połączenie

Złączenie naturalne to złączenie, w którym wybierane są tylko te kolumny, które się nie powtarzają. Zwykle robi się to poprzez zapis (SELECT *) dla jednej tabeli i określenie listy pól dla pozostałych tabel. Przykład:

Run SQLSELECT SP.*, S.Country
FROM Sumproduct AS SP, Sellers AS S 
WHERE SP.City = S.City

W tym przykładzie symbol wieloznaczny (*) jest używany tylko w przypadku pierwszej tabeli. Wszystkie pozostałe kolumny są określone jawnie, więc zduplikowane kolumny nie są wybierane.

4. Kombinacja zewnętrzna (OUTER JOIN)

Zwykle podczas łączenia wiersze jednej tabeli są łączone z odpowiadającymi im wierszami innej tabeli, jednak w niektórych przypadkach może zaistnieć konieczność uwzględnienia w wynikach wierszy, które nie mają powiązanych wierszy w innej tabeli (czyli wszystkie wybierane są wiersze z jednej tabeli i dodawane są tylko powiązane wiersze z innej). Połączenie tego typu nazywa się zewnętrznym. W tym celu używane są słowa kluczowe OUTER JOIN ... ON ... z przedrostkiem LEFT lub RIGHT.

Rozważmy przykład, po wcześniejszym dodaniu nowego sprzedawcy - Semuela Pitera, który nie ma jeszcze sprzedaży, do tabeli Sellers:

Run SQLSELECT Seller_name, SUM(Quantity) AS Qty
FROM Sellers2 
LEFT OUTER JOIN Sumproduct 
ON Sellers2.City = Sumproduct.City
GROUP BY Seller_name

Dzięki temu zapytaniu wyciągnęliśmy z bazy listę wszystkich sprzedawców i obliczyliśmy łączną ilość sprzedanych im towarów we wszystkich miesiącach. Widzimy, że nie ma sprzedaży dla nowego sprzedawcy Semuela Pitera. Gdybyśmy zastosowali złączenie wewnętrzne, nie zobaczylibyśmy nowego sprzedawcy, ponieważ nie ma on żadnych rekordów w tabeli Sumproduct. Kierunek kombinacji możemy zmienić także nie tylko poprzez pisanie LEFT lub RIGHT, ale także po prostu zmieniając kolejność tabel (tzn. następujące dwa rekordy dadzą ten sam wynik: Sellers LEFT OUTER JOIN Sumproduct i Sumproduct RIGHT OUTER JOIN Sellers).

Ponadto niektóre systemy DBMS pozwalają na zewnętrzne sprzężenia w uproszczonym rekordzie przy użyciu znaków *= i =*, co odpowiada odpowiednio LEFT OUTER JOIN i RIGHT OUTER JOIN. Zatem poprzednie zapytanie można przepisać w następujący sposób:

SELECT Seller_name, SUM(Quantity) AS Qty
FROM Sellers, Sumproduct
WHERE Sellers.City *= Sumproduct.City

Niestety MS Access nie obsługuje skróconego rekordu dla sprzężenia zewnętrznego.

5. Pełne złączenie zewnętrzne (FULL OUTER JOIN)

Istnieje również inny rodzaj złączenia zewnętrznego - pełne złączenie zewnętrzne, które wyświetla wszystkie wiersze z obu tabel i łączy tylko te, które mogą być powiązane. Składnia pełnego sprzężenia zewnętrznego jest następująca:

SELECT Seller_name, Product
FROM Sellers 
FULL OUTER JOIN Sumproduct 
ON Sellers.City = Sumproduct.City

Ponownie, pełne sprzężenie zewnętrzne nie jest obsługiwane przez następujące systemy DBMS: MS Access, MySQL, SQL Server i Sybase. Jak obejść tę niesprawiedliwość, rozważymy w następnej sekcji.