Sprzężenie SQL polega na uruchomieniu zapytania, które łączy wiele tabel.
W tym samouczku dotyczącym złączeń SQL przedstawiono podstawowe przykłady złączeń SQL, a także wprowadzenie do różnych typów złączeń.
Typy złączeń SQL
Standard ANSI SQL określa pięć typów złączeń wymienionych w poniższej tabeli.
Typ łączenia | Opis |
---|---|
INNER JOIN | Zwraca wiersze, gdy w obu tabelach jest co najmniej jeden wiersz, który spełnia warunek złączenia. |
LEFT OUTER JOIN lub LEFT JOIN | Zwraca wiersze, które mają dane w lewej tabeli (po lewej stronie JOIN słowa kluczowego), nawet jeśli w prawej tabeli nie ma pasujących wierszy. |
RIGHT OUTER JOIN lub RIGHT JOIN | Zwraca wiersze, które zawierają dane w prawej tabeli (na prawo od JOIN słowa kluczowego), nawet jeśli w lewej tabeli nie ma pasujących wierszy. |
FULL OUTER JOIN lub FULL JOIN | Zwraca wszystkie wiersze, o ile w jednej z tabel znajdują się pasujące dane. |
CROSS JOIN | Zwraca wiersze, które łączą każdy wiersz z pierwszej tabeli z każdym wierszem z drugiej tabeli. |
Istnieją również inne terminy dla różnych operacji łączenia, takie jak:
Dołącz | Opis |
---|---|
Dołącz samodzielnie | Kiedy tabela łączy się ze sobą. |
Naturalne połączenie | Złączenie niejawne oparte na wspólnych kolumnach w dwóch łączonych tabelach. |
Łączenie równo | Złączenie zawierające tylko porównania równości w predykacie złączenia. |
Składnia łączenia SQL
Sprzężenia wewnętrzne można określić w FROM
lub WHERE
klauzule. Złącza zewnętrzne i sprzężenia krzyżowe można określić w FROM
tylko klauzula.
Aby utworzyć sprzężenie SQL w FROM
klauzula, zrób coś takiego:
SELECT *
FROM Table1 < JoinType > Table2 [ ON ( JoinCondition ) ]
Gdzie JoinType
określa, jaki rodzaj łączenia jest wykonywany, a JoinCondition
definiuje predykat do oceny dla każdej pary połączonych wierszy.
Aby określić sprzężenie w WHERE
klauzula, zrób coś takiego:
SELECT *
FROM Table1, Table2 [ WHERE ( JoinCondition ) ]
Ponownie, JoinCondition
definiuje predykat do oceny dla każdej pary połączonych wierszy.
Ponadto wszystko ujęte w nawiasy kwadratowe ([]
) jest opcjonalne.
Przykładowe tabele dla przykładów w tym samouczku
Większość przykładów w tym samouczku wykonuje sprzężenia w poniższych dwóch tabelach.
PetTypes
tabela:
+-------------+-----------+ | PetTypeId | PetType | |-------------+-----------| | 1 | Bird | | 2 | Cat | | 3 | Dog | | 4 | Rabbit | +-------------+-----------+ (4 rows affected)
Pets
tabela:
+---------+-------------+-----------+-----------+------------+ | PetId | PetTypeId | OwnerId | PetName | DOB | |---------+-------------+-----------+-----------+------------| | 1 | 2 | 3 | Fluffy | 2020-11-20 | | 2 | 3 | 3 | Fetch | 2019-08-16 | | 3 | 2 | 2 | Scratch | 2018-10-01 | | 4 | 3 | 3 | Wag | 2020-03-15 | | 5 | 1 | 1 | Tweet | 2020-11-28 | | 6 | 3 | 4 | Fluffy | 2020-09-17 | | 7 | 3 | 2 | Bark | NULL | | 8 | 2 | 4 | Meow | NULL | +---------+-------------+-----------+-----------+------------+ (8 rows affected)
Łączenie wewnętrzne
SQL INNER JOIN
zwraca wiersze, gdy w obu tabelach jest co najmniej jeden wiersz, który spełnia warunek złączenia.
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets
INNER JOIN PetTypes
ON Pets.PetTypeId = PetTypes.PetTypeId;
Wynik:
-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+ (8 rows affected)
Aby określić sprzężenie wewnętrzne w FROM
klauzula, używamy INNER JOIN
. Używamy również ON
słowo kluczowe, aby zdefiniować predykat do oceny dla każdej pary połączonych wierszy.
Niezależnie od typu sprzężenia kwalifikujemy nazwy naszych kolumn nazwami tabel. Powodem, dla którego to robimy, jest uniknięcie niejasności dotyczących nazw kolumn między tabelami. Obie tabele mogą mieć kolumny o tej samej nazwie (jak w naszym przykładzie), a w takich przypadkach DBMS nie będzie wiedział, do której kolumny się odnosisz. Poprzedzenie nazw kolumn ich nazwami tabel gwarantuje, że odwołujesz się do właściwej kolumny i zapobiega wszelkim błędom, które mogą wynikać z jakichkolwiek niejasności co do kolumny, do której się odnosisz.
W tym przykładzie obie tabele mają PetTypeId
kolumna. Pets.PetTypeId
kolumna jest kluczem obcym do PetTypes.PetTypeId
kolumna, która jest kluczem podstawowym dla tej tabeli.
W tym przykładzie widzimy, że zwracane są wszystkie zwierzęta, ale nie wszystkie typy zwierząt. W Pets
nie ma królików tabela, a więc Rabbits
typ zwierzaka nie jest zwracany.
Powód, dla którego Rabbits
typ nie jest zwracany, ponieważ INNER JOIN
zwraca wiersze tylko wtedy, gdy w obu tabelach znajduje się co najmniej jeden wiersz, który spełnia warunek złączenia. W tym przypadku Rabbits
znajduje się tylko w jednej tabeli (PetTypes
tabeli).
Zauważ, że typ łączenia jest opcjonalny. Dlatego większość (jeśli nie wszystkie) DBMS pozwala na pominięcie INNER
słowo kluczowe. Gdy to pominiesz (tzn. określ tylko JOIN
), zakłada się, że jest to sprzężenie wewnętrzne.
Dlatego możemy przepisać powyższy przykład do tego:
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets
JOIN PetTypes
ON Pets.PetTypeId = PetTypes.PetTypeId;
Podobnie jak w przypadku każdej instrukcji SQL, FROM
klauzula może znajdować się w jednym wierszu, jeśli wolisz:
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets JOIN PetTypes ON Pets.PetTypeId = PetTypes.PetTypeId;
Aliasy
Powszechną praktyką jest używanie aliasów tabel podczas wykonywania złączeń SQL. Aliasy pomagają uczynić kod bardziej zwięzłym i łatwiejszym do odczytania.
Dlatego możemy zmienić poprzedni przykład na następujący:
SELECT
p.PetName,
pt.PetType
FROM Pets p INNER JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Wynik:
-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+ (8 rows affected)
Złączenie równoprawne
Powyższe złączenie może być również określane jako equi-join . Złączenie ekwiwalentne to złączenie zawierające tylko porównania równości w predykacie złączenia.
Inny sposób napisania powyższego sprzężenia jest taki:
SELECT
p.PetName,
pt.PetType
FROM
Pets p,
PetTypes pt
WHERE p.PetTypeId = pt.PetTypeId;
Wynik:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+
To jest przykład określenia sprzężenia wewnętrznego w WHERE
klauzula. Po prostu dostarczyliśmy listę tabel oddzielonych przecinkami, a następnie WHERE
stan :schorzenie. Gdybyśmy pominęli WHERE
warunek, otrzymalibyśmy CROSS JOIN
.
Dla wielu początkujących powyższa składnia jest znacznie łatwiejsza do zrozumienia niż INNER JOIN
składnia. Możesz użyć tej składni, jeśli wolisz, jednak pamiętaj, że większość specjalistów SQL woli używać INNER JOIN
składnia z poprzedniego przykładu.
Zobacz SQL Inner Join, aby uzyskać więcej przykładów, w tym złącze wewnętrzne, które łączy 3 tabele.
Właściwe połączenie
Znany również jako RIGHT OUTER JOIN
, RIGHT JOIN
zwraca wiersze, które mają dane w prawej tabeli (na prawo od JOIN
słowa kluczowego), nawet jeśli w lewej tabeli nie ma pasujących wierszy.
SELECT
p.PetName,
pt.PetType
FROM Pets p
RIGHT JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Wynik:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Tweet | Bird | | Fluffy | Cat | | Scratch | Cat | | Meow | Cat | | Fetch | Dog | | Wag | Dog | | Fluffy | Dog | | Bark | Dog | | NULL | Rabbit | +-----------+-----------+ (9 rows affected)
W tym przypadku otrzymaliśmy dodatkowy PetType
wartość – Rabbit
– mimo że nie ma zwierzaka w Pets
tabeli tego typu. Powoduje to NULL
wartość w PetName
kolumna przeciwko Rabbit
.
Zobacz SQL Right Join, aby uzyskać więcej przykładów, w tym prawego sprzężenia, które łączy 3 tabele.
Lewe połączenie
Znany również jako LEFT OUTER JOIN
, SQL LEFT JOIN
zwraca wiersze, które mają dane w lewej tabeli (po lewej stronie JOIN
słowa kluczowego), nawet jeśli w prawej tabeli nie ma pasujących wierszy.
Jest to przeciwieństwo RIGHT JOIN
.
Jeśli zmienimy poprzedni przykład na użycie lewego sprzężenia, otrzymamy następujący wynik.
SELECT
p.PetName,
pt.PetType
FROM Pets p
LEFT JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Wynik:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+ (8 rows affected)
W tym konkretnym przypadku nasze wyniki są takie same jak w przypadku sprzężenia wewnętrznego.
Jeśli jednak zmienimy kolejność tabel w naszym FROM
klauzula, otrzymamy podobny wynik do prawego sprzężenia w poprzednim przykładzie.
SELECT
p.PetName,
pt.PetType
FROM PetTypes pt
LEFT JOIN Pets p
ON p.PetTypeId = pt.PetTypeId;
Wynik:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Tweet | Bird | | Fluffy | Cat | | Scratch | Cat | | Meow | Cat | | Fetch | Dog | | Wag | Dog | | Fluffy | Dog | | Bark | Dog | | NULL | Rabbit | +-----------+-----------+ (9 rows affected)
Możesz więc zobaczyć, że każda wynikowa różnica między lewym i prawym złączeniem zależy wyłącznie od tego, jak uporządkujesz kolumny w FROM
klauzula.
Zobacz SQL Left Join, aby uzyskać więcej przykładów, w tym lewe sprzężenie, które łączy 3 tabele.
Pełne połączenie
SQL FULL JOIN
(lub FULL OUTER JOIN
) zwraca wszystkie wiersze, o ile w jednej z tabel znajdują się pasujące dane.
Innymi słowy, to tak, jakby w jednym sprzężeniu znajdowało się zarówno lewe, jak i prawe sprzężenie.
Oto przykład pełnego dołączenia.
SELECT
p.PetName,
pt.PetType
FROM Pets p
FULL JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Wynik:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | | NULL | Rabbit | +-----------+-----------+ (9 rows affected)
Zwraca to ten sam wynik, który otrzymaliśmy przy prawym sprzężeniu, ale zwróciłby inny wynik, gdyby w lewej tabeli był wiersz, który nie ma odpowiadającej wartości w prawej tabeli.
Zamieńmy nazwy tabel i uruchommy ponownie.
SELECT
p.PetName,
pt.PetType
FROM PetTypes pt
FULL JOIN Pets p
ON p.PetTypeId = pt.PetTypeId;
Wynik:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Tweet | Bird | | Fluffy | Cat | | Scratch | Cat | | Meow | Cat | | Fetch | Dog | | Wag | Dog | | Fluffy | Dog | | Bark | Dog | | NULL | Rabbit | +-----------+-----------+ (9 rows affected)
Ten sam wynik.
Zobacz SQL Full Join, aby uzyskać więcej przykładów, w tym pełne złączenie, które łączy 3 tabele.
Łączenie krzyża
SQL CROSS JOIN
zwraca wiersze, które łączą każdy wiersz z pierwszej tabeli z każdym wierszem z drugiej tabeli.
Innymi słowy, zwraca iloczyn kartezjański wierszy z tabel w łączeniu.
SELECT
p.PetName,
pt.PetType
FROM Pets p
CROSS JOIN PetTypes pt;
Wynik:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Bird | | Fetch | Bird | | Scratch | Bird | | Wag | Bird | | Tweet | Bird | | Fluffy | Bird | | Bark | Bird | | Meow | Bird | | Fluffy | Cat | | Fetch | Cat | | Scratch | Cat | | Wag | Cat | | Tweet | Cat | | Fluffy | Cat | | Bark | Cat | | Meow | Cat | | Fluffy | Dog | | Fetch | Dog | | Scratch | Dog | | Wag | Dog | | Tweet | Dog | | Fluffy | Dog | | Bark | Dog | | Meow | Dog | | Fluffy | Rabbit | | Fetch | Rabbit | | Scratch | Rabbit | | Wag | Rabbit | | Tweet | Rabbit | | Fluffy | Rabbit | | Bark | Rabbit | | Meow | Rabbit | +-----------+-----------+ (32 rows affected)
Jak prawdopodobnie możesz sobie wyobrazić, może to być bardzo niebezpieczne, jeśli użyjesz go na niewłaściwych stołach.
To tak samo, jak zrobienie tego:
SELECT
p.PetName,
pt.PetType
FROM Pets p, PetTypes pt;
Możesz dodać WHERE
klauzula sprzężenia krzyżowego, która zmieni je w sprzężenie wewnętrzne.
Tak:
SELECT
p.PetName,
pt.PetType
FROM Pets p
CROSS JOIN PetTypes pt
WHERE p.PetTypeId = pt.PetTypeId;
Wynik:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+ (8 rows affected)
Zobacz SQL Cross Join, aby uzyskać więcej przykładów.
Naturalne połączenie
SQL NATURAL JOIN
jest typem sprzężenia ekwiwalentnego, w którym predykat łączenia powstaje niejawnie przez porównanie wszystkich kolumn w obu tabelach, które mają te same nazwy kolumn w połączonych tabelach.
Zestaw wyników zawiera tylko jedną kolumnę dla każdej pary kolumn o tej samej nazwie. Jeśli nie zostaną znalezione żadne kolumny o tych samych nazwach, wynikiem będzie sprzężenie krzyżowe.
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets NATURAL JOIN PetTypes;
Wynik:
petname | pettype ---------+--------- Fluffy | Cat Fetch | Dog Scratch | Cat Wag | Dog Tweet | Bird Fluffy | Dog Bark | Dog Meow | Cat (8 rows)
W rzeczywistości sprzężenie naturalne nie jest w rzeczywistości typem sprzężenia, zgodnie ze standardem ANSI. Jest to słowo kluczowe, które możesz opcjonalnie wstawić, aby połączenie było połączeniem naturalnym.
Dlatego możemy zmienić powyższy przykład na NATURAL INNER JOIN
gdybyśmy chcieli:
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets NATURAL INNER JOIN PetTypes;
Jak wspomniano wcześniej, złączenia wewnętrzne są domyślnym typem złączenia, więc jeśli pominiesz typ złączenia (np. INNER
, LEFT
, RIGHT
itp.), to jest traktowane jako sprzężenie wewnętrzne.
Jeśli formatowanie tych wyników wygląda inaczej niż poprzednie, to dlatego, że musiałem przeskoczyć do PostgreSQL, aby uruchomić to zapytanie. Poprzednie przykłady uruchomiłem w SQL Server, ale SQL Server nie obsługuje łączenia naturalnego.
Zobacz SQL Natural Join, aby uzyskać więcej przykładów, w tym naturalne połączenie, które łączy 3 tabele.
Samoprzyłączanie
SQL SELF JOIN
dołącza do siebie stół.
Klasycznym przykładem samodzielnego sprzężenia jest tabela Pracownicy. W takiej tabeli jeden pracownik może podlegać innemu pracownikowi. Dlatego możesz użyć samodzielnego łączenia, aby dołączyć do tabeli w kolumnie Identyfikator pracownika i Identyfikator menedżera.
Załóżmy, że mamy następującą tabelę:
+--------------+-------------+------------+-------------+ | EmployeeId | FirstName | LastName | ReportsTo | |--------------+-------------+------------+-------------| | 1 | Homer | Connery | NULL | | 2 | Bart | Pitt | 1 | | 3 | Maggie | Griffin | 1 | | 4 | Peter | Farnsworth | 2 | | 5 | Marge | Morrison | NULL | | 6 | Lisa | Batch | 5 | | 7 | Dave | Zuckerberg | 6 | | 8 | Vlad | Cook | 7 | +--------------+-------------+------------+-------------+
Możemy wykonać samodzielne dołączenie na tym stole, aby zwrócić wszystkich pracowników i ich menedżerów.
SELECT
CONCAT(e1.FirstName, ' ', e1.LastName) AS Employee,
CONCAT(e2.FirstName, ' ', e2.LastName) AS Manager
FROM Employees e1
LEFT JOIN Employees e2
ON e1.ReportsTo = e2.EmployeeId;
Wynik:
+------------------+-----------------+ | Employee | Manager | |------------------+-----------------| | Homer Connery | | | Bart Pitt | Homer Connery | | Maggie Griffin | Homer Connery | | Peter Farnsworth | Bart Pitt | | Marge Morrison | | | Lisa Batch | Marge Morrison | | Dave Zuckerberg | Lisa Batch | | Vlad Cook | Dave Zuckerberg | +------------------+-----------------+
Zobacz SQL Self Join, aby uzyskać więcej przykładów.