Database
 sql >> Database >  >> RDS >> Database

Esercitazione sui join SQL

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.