Questo articolo fornisce una panoramica del FULL JOIN
in SQL, oltre ad alcuni esempi di base.
Il FULL JOIN
di SQL (o FULL OUTER JOIN
) restituisce tutte le righe, purché ci siano dati corrispondenti in una delle tabelle.
È come avere entrambi un join sinistro destro in un join.
Sintassi
Specificare un join completo nel FROM
clausola. Puoi usare sia il FULL JOIN
o FULL OUTER JOIN
sintassi.
Usando il FULL JOIN
sintassi:
SELECT *
FROM Table1 FULL JOIN Table2
ON Table1.Column = Table2.Column;
Usando il FULL OUTER JOIN
sintassi:
SELECT *
FROM Table1 FULL OUTER JOIN Table2
ON Table1.Column = Table2.Column;
Entrambi fanno esattamente la stessa cosa. È solo che il OUTER
la parola chiave è facoltativa.
Esempi
Ecco alcuni esempi da dimostrare.
Dati di esempio
Innanzitutto, ecco le tabelle che useremo per gli esempi.
I PetTypes
tabella:
+-------------+-----------+ | PetTypeId | PetType | |-------------+-----------| | 1 | Bird | | 2 | Cat | | 3 | Dog | | 4 | Rabbit | +-------------+-----------+ (4 rows affected)
Gli Pets
tabella:
+---------+-------------+-----------+-----------+------------+ | 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)
I Owners
tabella:
+-----------+-------------+------------+----------------+-------------------+ | 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] | +-----------+-------------+------------+----------------+-------------------+
Nota che:
- Il
PetTypeId
colonna delPets
table è una chiave esterna diPetTypeId
deiPetTypes
table (che è la chiave primaria di quella tabella). - Il
OwnerId
colonna delPets
table è una chiave esterna diOwnerId
colonna deiOwners
tabella.
La query di partecipazione completa
Ecco un esempio di esecuzione di un full join su due di queste tabelle.
SELECT
p.PetName,
pt.PetType
FROM Pets p
FULL JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Risultato:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Tweet | Bird | | Fluffy | Cat | | Scratch | Cat | | Meow | Cat | | Fetch | Dog | | Wag | Dog | | Fluffy | Dog | | Bark | Dog | | NULL | Rabbit | +-----------+-----------+ (9 rows affected)
In questo esempio, otteniamo un PetType
valore che non corrisponde a un PetName
. Questo perché non ci sono conigli come animali domestici. Ma il join completo provoca Rabbit
da restituire, anche se non ci sono animali nel Pets
tabella di quel tipo. Ciò risulta in un NULL
valore nel PetName
colonna contro Rabbit
.
Questo è lo stesso risultato che avremmo ottenuto se avessimo usato un join corretto, perché PetTypes
la tabella è a destra di JOIN
parola chiave. Questo non sarebbe successo con un join sinistro, perché PetTypes
la tabella non è a sinistra di JOIN
parola chiave. Se volessimo ricrearlo con un join sinistro, dovremmo cambiare l'ordine delle tabelle, in modo che i PetTypes
la tabella era a sinistra di JOIN
parola chiave.
Ecco cosa succede se cambiamo l'ordine della tabella nella nostra query quando si utilizza un join completo.
SELECT
p.PetName,
pt.PetType
FROM PetTypes pt
FULL JOIN Pets p
ON p.PetTypeId = pt.PetTypeId;
Risultato:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Tweet | Bird | | Fluffy | Cat | | Scratch | Cat | | Meow | Cat | | Fetch | Dog | | Wag | Dog | | Fluffy | Dog | | Bark | Dog | | NULL | Rabbit | +-----------+-----------+ (9 rows affected)
Otteniamo esattamente lo stesso risultato. Questo perché il join completo restituisce tutte le righe, purché ci siano dati corrispondenti in una delle tabelle. Come accennato, è come avere un join sinistro e destro in un join.
Full Join su 3 tavoli
Ecco un esempio di esecuzione di un full join su tutti e tre i tavoli.
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;
Risultato:
+-----------+-----------+----------------+ | 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)
Questa volta abbiamo un proprietario di un animale domestico che non ha un animale domestico, così come un tipo di animale domestico che non è assegnato a un animale domestico.
Se mescoliamo l'ordine delle tabelle, otteniamo lo stesso risultato, sebbene le righe siano elencate in un ordine diverso.
SELECT
p.PetName,
pt.PetType,
CONCAT(o.FirstName, ' ', o.LastName) AS PetOwner
FROM PetTypes pt FULL JOIN Pets p
ON p.PetTypeId = pt.PetTypeId
FULL JOIN Owners o
ON p.OwnerId = o.OwnerId;
Risultato:
-----------+-----------+----------------+ | 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 | | | NULL | NULL | Woody Eastwood | +-----------+-----------+----------------+ (10 rows affected)
E se li mescoliamo ancora una volta, otteniamo sempre lo stesso risultato.
SELECT
p.PetName,
pt.PetType,
CONCAT(o.FirstName, ' ', o.LastName) AS PetOwner
FROM Pets p FULL JOIN Owners o
ON p.OwnerId = o.OwnerId
FULL JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Risultato:
+-----------+-----------+----------------+ | PetName | PetType | PetOwner | |-----------+-----------+----------------| | Fluffy | Cat | Nancy Simpson | | Fetch | Dog | Nancy Simpson | | Scratch | Cat | Bart Pitt | | Wag | Dog | Nancy Simpson | | Tweet | Bird | Homer Connery | | Fluffy | Dog | Boris Trump | | Bark | Dog | Bart Pitt | | Meow | Cat | Boris Trump | | NULL | NULL | Woody Eastwood | | NULL | Rabbit | | +-----------+-----------+----------------+ (10 rows affected)
Se ti stai chiedendo perché l'ultimo PetOwner
non è NULL
(come ultimo il PetName
is), è perché è il risultato di una concatenazione di stringhe. Ho usato T-SQL CONCAT()
funzione per concatenare il nome e il cognome del proprietario.