W SQL możesz połączyć trzy lub więcej stołów, dodając kolejne połączenie po pierwszym.
Możesz także uruchomić złączenia zagnieżdżone, określając jedno złącze jako warunek złączenia dla innego.
Składnia
Najpopularniejszy sposób łączenia trzech stołów wygląda mniej więcej tak:
SELECT *
FROM Table1
INNER JOIN Table2
ON Condition
INNER JOIN Table3
ON Condition;
Wykorzystuje to sprzężenie wewnętrzne, ale możesz określić żądany typ sprzężenia, tak jak w przypadku każdego innego sprzężenia. W razie potrzeby możesz również łączyć typy połączeń (przykład poniżej).
Możesz także użyć sprzężeń zagnieżdżonych, określając jedno sprzężenie jako warunek sprzężenia dla innego sprzężenia. Tak:
SELECT *
FROM Table1
JOIN (Table2
JOIN Table3
ON Condition)
ON Condition;
Dane przykładowe – 3 tabele
Załóżmy, że mamy następujące trzy tabele.
Customers
tabela:
+--------------+----------------+----------------+----------------+ | CustomerId | CustomerName | PostalCityId | PhoneNumber | |--------------+----------------+----------------+----------------| | 1 | Homer McKenzie | 19586 | (308) 555-0100 | | 2 | Marge Pratt | 33475 | (406) 555-0100 | | 3 | Vlad Bernanke | NULL | (480) 555-0100 | | 4 | Bart Pitt | 21692 | (316) 555-0100 | | 5 | Lisa McQueen | 12748 | (212) 555-0100 | | 6 | Steve Simpson | 17054 | (701) 555-0100 | | 7 | Vinn Allen | 12152 | (423) 555-0100 | | 8 | Veejay Smith | 3673 | (303) 555-0100 | | 9 | Kasey Chin | 23805 | (201) 555-0100 | | 10 | Borat Lee | 37403 | (701) 555-0100 | +--------------+----------------+----------------+----------------+ (10 rows affected)
Cities
tabela:
+----------+----------------+-------------------+--------------+ | CityId | CityName | StateProvinceId | Population | |----------+----------------+-------------------+--------------| | 3673 | Bow Mar | 6 | 866 | | 12152 | Frankewing | 44 | NULL | | 12748 | Gasport | 33 | 1248 | | 21692 | Medicine Lodge | 17 | 2009 | | 26483 | Peeples Valley | 3 | 428 | | 33475 | Sylvanite | 27 | 103 | | 17054 | Jessie | 35 | 25 | | 19586 | Lisco | 28 | NULL | | 37403 | Wimbledon | 35 | 216 | +----------+----------------+-------------------+--------------+ (9 rows affected)
StateProvinces
tabela:
+-------------------+---------------------+---------------------+-------------+--------------+ | StateProvinceId | StateProvinceCode | StateProvinceName | CountryId | Population | |-------------------+---------------------+---------------------+-------------+--------------| | 3 | AZ | Arizona | 230 | 6891688 | | 6 | CO | Colorado | 230 | 5698265 | | 17 | KS | Kansas | 230 | 2893957 | | 28 | NE | Nebraska | 230 | 1943256 | | 31 | NJ | New Jersey | 230 | 8899339 | | 33 | NY | New York | 230 | 20437172 | | 35 | ND | North Dakota | 230 | 723393 | | 44 | TN | Tennessee | 230 | 6495978 | +-------------------+---------------------+---------------------+-------------+--------------+ (8 rows affected)
Przykład 1 – Wewnętrzne połączenie 3 stołów
Najpopularniejszym typem sprzężenia jest sprzężenie wewnętrzne, więc od tego zaczniemy.
Oto przykład łączenia powyższych trzech tabel za pomocą dwóch sprzężeń wewnętrznych.
SELECT
s.StateProvinceName,
ci.CityName,
cu.CustomerName
FROM StateProvinces s
INNER JOIN Cities AS ci
ON ci.StateProvinceID = s.StateProvinceID
INNER JOIN Customers cu
ON cu.PostalCityId = ci.CityId;
Wynik:
+---------------------+----------------+----------------+ | StateProvinceName | CityName | CustomerName | |---------------------+----------------+----------------| | Nebraska | Lisco | Homer McKenzie | | Kansas | Medicine Lodge | Bart Pitt | | New York | Gasport | Lisa McQueen | | North Dakota | Jessie | Steve Simpson | | Tennessee | Frankewing | Vinn Allen | | Colorado | Bow Mar | Veejay Smith | | North Dakota | Wimbledon | Borat Lee | +---------------------+----------------+----------------+ (7 rows affected)
Przykład 2 – Łączenie typów złączeń
Możesz łączyć typy przyłączeń podczas dołączania do trzech lub więcej stołów.
Oto przykład połączenia sprzężenia wewnętrznego z sprzężeniem lewym.
SELECT
s.StateProvinceName,
ci.CityName,
cu.CustomerName
FROM StateProvinces s
INNER JOIN Cities AS ci
ON ci.StateProvinceID = s.StateProvinceID
LEFT JOIN Customers cu
ON cu.PostalCityId = ci.CityId;
Wynik:
---------------------+----------------+----------------+ | StateProvinceName | CityName | CustomerName | |---------------------+----------------+----------------| | Colorado | Bow Mar | Veejay Smith | | Tennessee | Frankewing | Vinn Allen | | New York | Gasport | Lisa McQueen | | Kansas | Medicine Lodge | Bart Pitt | | Arizona | Peeples Valley | NULL | | North Dakota | Jessie | Steve Simpson | | Nebraska | Lisco | Homer McKenzie | | North Dakota | Wimbledon | Borat Lee | +---------------------+----------------+----------------+ (8 rows affected)
W tym przypadku mamy miasto (Peeples Valley), które nie ma jeszcze klientów.
Powodem, dla którego możemy teraz zobaczyć te informacje, jest to, że lewe sprzężenie zwraca wiersze, które mają dane w lewej tabeli, nawet jeśli w lewej tabeli nie ma pasujących wierszy.
Poprzedni przykład, który łączył dwa sprzężenia wewnętrzne, nie zwrócił tego wiersza, ponieważ sprzężenia wewnętrzne odrzucają niedopasowane wiersze z obu tabel. Zwraca wiersze tylko wtedy, gdy w obu tabelach znajduje się co najmniej jeden wiersz, który spełnia warunek złączenia.
Nowe przykładowe dane – 3 różne tabele
W przypadku pozostałych przykładów użyjemy poniższych tabel.
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)
Owners
tabela:
+-----------+-------------+------------+----------------+-------------------+ | OwnerId | FirstName | LastName | Phone | Email | |-----------+-------------+------------+----------------+-------------------| | 1 | Homer | Connery | (308) 555-0100 | [email protected] | | 2 | Bart | Pitt | (231) 465-3497 | [email protected] | | 3 | Nancy | Simpson | (489) 591-0408 | NULL | | 4 | Boris | Trump | (349) 611-8908 | NULL | | 5 | Woody | Eastwood | (308) 555-0112 | [email protected] | +-----------+-------------+------------+----------------+-------------------+
Pamiętaj, że:
PetTypeId
kolumnaPets
tabela jest kluczem obcymPetTypeId
PetTypes
tabela (która jest kluczem podstawowym tej tabeli).OwnerId
kolumnaPets
tabela jest kluczem obcymOwnerId
kolumnaOwners
stół.
Przykład 3 – lewe łączenie 3 stołów
Zróbmy złączenie trzech tabel przy użyciu dwóch sprzężeń lewych.
Oto przykład uruchomienia dwóch lewych złączeń przeciwko tym tabelom.
SELECT
p.PetName,
pt.PetType,
CONCAT(o.FirstName, ' ', o.LastName) AS PetOwner
FROM Owners o LEFT JOIN Pets p
ON p.OwnerId = o.OwnerId
LEFT JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Wynik:
+-----------+-----------+----------------+ | PetName | PetType | PetOwner | |-----------+-----------+----------------| | Tweet | Bird | Homer Connery | | Scratch | Cat | Bart Pitt | | Bark | Dog | Bart Pitt | | Fluffy | Cat | Nancy Simpson | | Fetch | Dog | Nancy Simpson | | Wag | Dog | Nancy Simpson | | Fluffy | Dog | Boris Trump | | Meow | Cat | Boris Trump | | NULL | NULL | Woody Eastwood | +-----------+-----------+----------------+ (9 rows affected)
Tutaj mamy właściciela zwierzaka, który nie ma zwierzaka. Możemy to zweryfikować, patrząc na Pets.OwnerId
i widząc, że nie ma wartości odpowiadającej OwnerId
Woody'ego Eastwooda w Owners
tabela.
Przykład 4 – Prawe łączenie 3 stołów
Prawe sprzężenie jest przeciwieństwem lewego sprzężenia. Oto przykład wykorzystujący te same trzy tabele.
SELECT
p.PetName,
pt.PetType,
CONCAT(o.FirstName, ' ', o.LastName) AS PetOwner
FROM Pets p RIGHT JOIN Owners o
ON p.OwnerId = o.OwnerId
RIGHT JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Wynik:
+-----------+-----------+---------------+ | PetName | PetType | PetOwner | |-----------+-----------+---------------| | Tweet | Bird | Homer Connery | | Fluffy | Cat | Nancy Simpson | | Scratch | Cat | Bart Pitt | | Meow | Cat | Boris Trump | | Fetch | Dog | Nancy Simpson | | Wag | Dog | Nancy Simpson | | Fluffy | Dog | Boris Trump | | Bark | Dog | Bart Pitt | | NULL | Rabbit | | +-----------+-----------+---------------+ (9 rows affected)
Tym razem dostaliśmy dodatkowy typ zwierzaka (Rabbit
), ale nie dodatkowego właściciela. Dzieje się tak, ponieważ złączenia prawe zwracają wiersze, które zawierają dane w prawej tabeli, nawet jeśli w lewej tabeli nie ma pasujących wierszy.
Przy okazji, powód ostatniego PetOwner
nie jest NULL
(jak ostatnio PetName
jest), ponieważ jest wynikiem konkatenacji ciągów. Użyłem T-SQL CONCAT()
funkcja łączenia imienia i nazwiska właściciela.
Przykład 5 – Pełne łączenie 3 stołów
Pełne sprzężenie jest jak lewe i prawe sprzężenie w jednym. Zwraca wszystkie wiersze, o ile w jednej z tabel znajdują się pasujące dane.
SELECT
p.PetName,
pt.PetType,
CONCAT(o.FirstName, ' ', o.LastName) AS PetOwner
FROM Owners o FULL JOIN Pets p
ON p.OwnerId = o.OwnerId
FULL JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Wynik:
+-----------+-----------+----------------+ | PetName | PetType | PetOwner | |-----------+-----------+----------------| | Tweet | Bird | Homer Connery | | Scratch | Cat | Bart Pitt | | Bark | Dog | Bart Pitt | | Fluffy | Cat | Nancy Simpson | | Fetch | Dog | Nancy Simpson | | Wag | Dog | Nancy Simpson | | Fluffy | Dog | Boris Trump | | Meow | Cat | Boris Trump | | NULL | NULL | Woody Eastwood | | NULL | Rabbit | | +-----------+-----------+----------------+ (10 rows affected)
Tym razem otrzymujemy kombinację wyników, które otrzymaliśmy w poprzednich dwóch przykładach.
Przykład 6 – Połączenia zagnieżdżone
Jak wspomniano, możesz również wykonać sprzężenia zagnieżdżone.
Oto przykład połączenia zagnieżdżonego.
SELECT
p.PetName,
pt.PetType,
CONCAT(o.FirstName, ' ', o.LastName) AS PetOwner
FROM Owners o
LEFT JOIN (Pets p
LEFT JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId)
ON p.OwnerId = o.OwnerId;
Wynik:
+-----------+-----------+----------------+ | PetName | PetType | PetOwner | |-----------+-----------+----------------| | Tweet | Bird | Homer Connery | | Scratch | Cat | Bart Pitt | | Bark | Dog | Bart Pitt | | Fluffy | Cat | Nancy Simpson | | Fetch | Dog | Nancy Simpson | | Wag | Dog | Nancy Simpson | | Fluffy | Dog | Boris Trump | | Meow | Cat | Boris Trump | | NULL | NULL | Woody Eastwood | +-----------+-----------+----------------+ (9 rows affected)