Un join SQL è il punto in cui esegui una query che unisce più tabelle.
Questa esercitazione sui join SQL presenta esempi di base di join SQL, nonché un'introduzione ai vari tipi di join.
Tipi di join SQL
Lo standard ANSI SQL specifica cinque tipi di join, come elencato nella tabella seguente.
Tipo di iscrizione | Descrizione |
---|---|
INNER JOIN | Restituisce le righe quando è presente almeno una riga in entrambe le tabelle che soddisfano la condizione di unione. |
LEFT OUTER JOIN o LEFT JOIN | Restituisce le righe che contengono dati nella tabella di sinistra (a sinistra di JOIN parola chiave), anche se non ci sono righe corrispondenti nella tabella di destra. |
RIGHT OUTER JOIN o RIGHT JOIN | Restituisce le righe che contengono dati nella tabella di destra (a destra di JOIN parola chiave), anche se non ci sono righe corrispondenti nella tabella di sinistra. |
FULL OUTER JOIN o FULL JOIN | Restituisce tutte le righe, purché ci siano dati corrispondenti in una delle tabelle. |
CROSS JOIN | Restituisce le righe che combinano ogni riga della prima tabella con ogni riga della seconda tabella. |
Esistono anche altri termini per varie operazioni di unione, come i seguenti:
Unisciti | Descrizione |
---|---|
Auto-unione | Quando una tabella si unisce a se stessa. |
Unità naturale | Un join implicito basato sulle colonne comuni nelle due tabelle da unire. |
Equi-join | Un join contenente solo confronti di uguaglianza nel predicato di join. |
Sintassi di join SQL
Gli inner join possono essere specificati in FROM
o WHERE
clausole. I giunti esterni e incrociati possono essere specificati in FROM
solo clausola.
Per creare un join SQL nel FROM
clausola, fai qualcosa del genere:
SELECT *
FROM Table1 < JoinType > Table2 [ ON ( JoinCondition ) ]
Dove JoinType
specifica che tipo di join viene eseguito e JoinCondition
definisce il predicato da valutare per ogni coppia di righe unite.
Per specificare un join in WHERE
clausola, fai qualcosa del genere:
SELECT *
FROM Table1, Table2 [ WHERE ( JoinCondition ) ]
Di nuovo, JoinCondition
definisce il predicato da valutare per ogni coppia di righe unite.
Inoltre, tutto racchiuso tra parentesi quadre ([]
) è facoltativo.
Tabelle di esempio per gli esempi in questo tutorial
La maggior parte degli esempi in questo tutorial esegue join rispetto alle due tabelle seguenti.
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)
L'unione interiore
Il INNER JOIN
di SQL restituisce righe quando è presente almeno una riga in entrambe le tabelle che soddisfa la condizione di unione.
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets
INNER JOIN PetTypes
ON Pets.PetTypeId = PetTypes.PetTypeId;
Risultato:
-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+ (8 rows affected)
Per specificare un inner join nel FROM
clausola, utilizziamo INNER JOIN
. Usiamo anche il ON
parola chiave per definire il predicato da valutare per ogni coppia di righe unite.
Indipendentemente dal tipo di join, qualifichiamo i nomi delle nostre colonne con i nomi delle tabelle. Il motivo per cui lo facciamo è evitare qualsiasi ambiguità riguardo ai nomi delle colonne tra le tabelle. Entrambe le tabelle potrebbero avere colonne con lo stesso nome (come nel nostro esempio) e in questi casi il DBMS non saprà a quale colonna ti riferisci. Prefissare i nomi delle colonne con i nomi delle tabelle assicura che stai facendo riferimento alla colonna giusta e previene eventuali errori che potrebbero derivare da qualsiasi ambiguità sulla colonna a cui ti riferisci.
In questo esempio, entrambe le tabelle hanno un PetTypeId
colonna. Il Pets.PetTypeId
column è una chiave esterna per PetTypes.PetTypeId
colonna, che è la chiave primaria per quella tabella.
In questo esempio, possiamo vedere che tutti gli animali domestici vengono restituiti, ma non tutti i tipi di animali domestici vengono restituiti. Non ci sono conigli nel Pets
tabella, e così i Rabbits
il tipo di animale domestico non viene restituito.
Il motivo per i Rabbits
il tipo non viene restituito è perché INNER JOIN
restituisce righe solo quando è presente almeno una riga in entrambe le tabelle che soddisfano la condizione di unione. In questo caso, Rabbits
è solo in una tabella (il PetTypes
tabella).
Si noti che il tipo di unione è facoltativo. Pertanto, la maggior parte (se non tutti) i DBMS ti consentono di omettere il INNER
parola chiave. Quando lo ometti (es. specifica solo JOIN
), si presume che sia un inner join.
Pertanto, potremmo riscrivere l'esempio sopra in questo:
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets
JOIN PetTypes
ON Pets.PetTypeId = PetTypes.PetTypeId;
Inoltre, come con qualsiasi istruzione SQL, il FROM
la clausola può essere su un'intera riga se preferisci:
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets JOIN PetTypes ON Pets.PetTypeId = PetTypes.PetTypeId;
Alias
È prassi comune utilizzare alias di tabella durante l'esecuzione di join SQL. Gli alias aiutano a rendere il codice più conciso e più facile da leggere.
Pertanto, potremmo cambiare l'esempio precedente in questo:
SELECT
p.PetName,
pt.PetType
FROM Pets p INNER JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Risultato:
-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+ (8 rows affected)
L'Equi-Join
L'unione di cui sopra può anche essere definita equi-join . Un equi-join è un join che contiene solo confronti di uguaglianza nel predicato di join.
Un altro modo per scrivere il join sopra è questo:
SELECT
p.PetName,
pt.PetType
FROM
Pets p,
PetTypes pt
WHERE p.PetTypeId = pt.PetTypeId;
Risultato:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+
Questo è un esempio di specifica di un inner join nel WHERE
clausola. Abbiamo semplicemente fornito un elenco separato da virgole delle tabelle, quindi un WHERE
condizione. Se avessimo omesso il WHERE
condizione, avremmo finito con un CROSS JOIN
.
Molti principianti trovano la sintassi di cui sopra molto più facile da capire rispetto a INNER JOIN
sintassi. Sentiti libero di usare questa sintassi se preferisci, tuttavia, tieni presente che la maggior parte dei professionisti SQL preferisce utilizzare il INNER JOIN
sintassi dell'esempio precedente.
Vedi SQL Inner Join per altri esempi, incluso un inner join che unisce 3 tabelle.
La giusta unione
Conosciuto anche come RIGHT OUTER JOIN
, il RIGHT JOIN
restituisce righe che contengono dati nella tabella di destra (a destra di JOIN
parola chiave), anche se non ci sono righe corrispondenti nella tabella di sinistra.
SELECT
p.PetName,
pt.PetType
FROM Pets p
RIGHT 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 caso, abbiamo un PetType
extra valore – Rabbit
– anche se non ci sono animali in Pets
tabella di quel tipo. Ciò risulta in un NULL
valore nel PetName
colonna contro Rabbit
.
Vedi SQL Right Join per altri esempi, incluso un right join che unisce 3 tabelle.
La sinistra si unisce
Conosciuto anche come LEFT OUTER JOIN
, l'SQL LEFT JOIN
restituisce righe che contengono dati nella tabella di sinistra (a sinistra di JOIN
parola chiave), anche se non ci sono righe corrispondenti nella tabella di destra.
Questo è l'opposto di RIGHT JOIN
.
Se modifichiamo l'esempio precedente per utilizzare un join sinistro, otteniamo il seguente risultato.
SELECT
p.PetName,
pt.PetType
FROM Pets p
LEFT JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Risultato:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+ (8 rows affected)
In questo caso particolare, i nostri risultati sono gli stessi del join interno.
Tuttavia, se scambiamo l'ordine delle tabelle nel nostro FROM
clausola, otterremo un risultato simile al join corretto nell'esempio precedente.
SELECT
p.PetName,
pt.PetType
FROM PetTypes pt
LEFT 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)
Quindi puoi vedere che qualsiasi differenza risultante tra i join sinistro e destro dipende esclusivamente da come ordini le colonne nel FROM
clausola.
Vedi SQL Left Join per altri esempi, incluso un left join che unisce 3 tabelle.
L'adesione completa
Il FULL JOIN
di SQL (o FULL OUTER JOIN
) restituisce tutte le righe, purché ci siano dati corrispondenti in una delle tabelle.
In altre parole, è come avere un join sinistro e destro in un join.
Ecco un esempio di full join.
SELECT
p.PetName,
pt.PetType
FROM Pets p
FULL JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;
Risultato:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | | NULL | Rabbit | +-----------+-----------+ (9 rows affected)
Questo restituisce lo stesso risultato che abbiamo ottenuto con il join corretto, ma avrebbe restituito un risultato diverso se ci fosse stata una riga nella tabella di sinistra che non aveva un valore corrispondente nella tabella di destra.
Scambiamo i nomi delle tabelle ed eseguiamolo di nuovo.
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)
Stesso risultato.
Vedi SQL Full Join per altri esempi, incluso un full join che unisce 3 tabelle.
La croce si unisce
Il CROSS JOIN
di SQL restituisce righe che combinano ogni riga della prima tabella con ogni riga della seconda tabella.
In altre parole, restituisce il prodotto cartesiano delle righe delle tabelle nel join.
SELECT
p.PetName,
pt.PetType
FROM Pets p
CROSS JOIN PetTypes pt;
Risultato:
+-----------+-----------+ | 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)
Come probabilmente puoi immaginare, questo potrebbe essere molto pericoloso se lo esegui contro i tavoli sbagliati.
È come fare questo:
SELECT
p.PetName,
pt.PetType
FROM Pets p, PetTypes pt;
Puoi aggiungere un WHERE
clausola a un cross join, che lo trasformerà in un inner join.
In questo modo:
SELECT
p.PetName,
pt.PetType
FROM Pets p
CROSS JOIN PetTypes pt
WHERE p.PetTypeId = pt.PetTypeId;
Risultato:
+-----------+-----------+ | PetName | PetType | |-----------+-----------| | Fluffy | Cat | | Fetch | Dog | | Scratch | Cat | | Wag | Dog | | Tweet | Bird | | Fluffy | Dog | | Bark | Dog | | Meow | Cat | +-----------+-----------+ (8 rows affected)
Vedi SQL Cross Join per altri esempi.
L'unione naturale
L'SQL NATURAL JOIN
è un tipo di equi-join in cui il predicato join nasce implicitamente confrontando tutte le colonne in entrambe le tabelle che hanno gli stessi nomi di colonna nelle tabelle unite.
Il set di risultati contiene solo una colonna per ogni coppia di colonne con lo stesso nome. Se non vengono trovate colonne con lo stesso nome, il risultato sarà un cross join.
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets NATURAL JOIN PetTypes;
Risultato:
petname | pettype ---------+--------- Fluffy | Cat Fetch | Dog Scratch | Cat Wag | Dog Tweet | Bird Fluffy | Dog Bark | Dog Meow | Cat (8 rows)
In realtà, il join naturale non è in realtà un tipo di join, come considerato dallo standard ANSI. È una parola chiave che puoi inserire opzionalmente per rendere il join un join naturale.
Pertanto, potremmo modificare l'esempio sopra in NATURAL INNER JOIN
se volessimo:
SELECT
Pets.PetName,
PetTypes.PetType
FROM Pets NATURAL INNER JOIN PetTypes;
Come accennato in precedenza, gli inner join sono il tipo di join predefinito, quindi se ometti il tipo di join (ad esempio, INNER
, LEFT
, RIGHT
, ecc.), quindi viene trattato come un inner join.
Se la formattazione di questi risultati sembra diversa dai risultati precedenti, è perché ho dovuto passare a PostgreSQL per eseguire questa query. Ho eseguito gli esempi precedenti in SQL Server, ma SQL Server non supporta il natural join.
Vedi SQL Natural Join per altri esempi, incluso un natural join che unisce 3 tabelle.
Il Self Join
L'SQL SELF JOIN
sta unendo un tavolo a se stesso.
Un classico esempio di self join è in una tabella Employees. In tale tabella, un dipendente potrebbe riferire a un altro dipendente. Pertanto, puoi utilizzare un self join per unirti alla tabella nella colonna ID dipendente e nella colonna ID manager.
Supponiamo di avere la seguente tabella:
+--------------+-------------+------------+-------------+ | 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 | +--------------+-------------+------------+-------------+
Possiamo fare un self join su questo tavolo per restituire tutti i dipendenti e i loro manager.
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;
Risultato:
+------------------+-----------------+ | 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 | +------------------+-----------------+
Vedi SQL Self Join per altri esempi.