Join (SQL)
La JOIN è una clausola del linguaggio SQL che serve a combinare le tuple di due o più relazioni di una base di dati. Lo standard ANSI definisce alcune specifiche per il linguaggio SQL sul tipo di JOIN da effettuare: INNER JOIN
, FULL JOIN
, LEFT JOIN
e RIGHT JOIN
, alle quali diversi DBMS aggiungono CROSS JOIN
. In alcuni casi è possibile che una tabella possa essere combinata con se stessa, in questo caso si parlerà di self-join.
Tabelle di esempio
[modifica | modifica wikitesto]Tutti gli esempi che verranno riportati di seguito faranno uso delle seguenti due tabelle:
Cognome | ID_dipartimento |
---|---|
Rossi | 31 |
Bianchi | 33 |
Mancini | 33 |
Santoro | 34 |
Monti | 34 |
Grassi | NULL
|
ID_dipartimento | Nome_dipartimento |
---|---|
31 | Vendite |
33 | Tecnico |
34 | Risorse umane |
35 | Promozione |
Dipartimenti.ID_dipartimento
è la chiave primaria che ha una cardinalità 0:n nei confronti del campo Impiegati.ID_dipartimento
.
Nota: Il dipartimento Promozione
della tabella Dipartimenti
non ha alcuna corrispondenza nella tabella Impiegati
. Mentre l'impiegato Grassi
non è stato assegnato ad alcun dipartimento (NULL).
Inner join
[modifica | modifica wikitesto]Una INNER JOIN
crea una nuova tabella combinando i valori delle due tabelle di partenza ( e ) basandosi su una certa regola di confronto. La query compara ogni riga della tabella con ciascuna riga della tabella cercando di soddisfare la regola di confronto definita. Quando la regola di join viene soddisfatta, i valori di tutte le colonne delle tabelle e vengono combinate in un'unica riga nella costruzione della tabella risultante. La INNER JOIN
è la forma di join usata più di frequente nelle applicazioni e rappresenta la modalità predefinita.
Per esempio, la seguente query unirà le due tabelle Impiegati
e Dipartimenti
usando la chiave primaria ID_dipartimento
che è la colonna presente in entrambe le tabelle. Quando ID_dipartimento
corrisponde in entrambe le tabelle (ovvero la regola è soddisfatta), la query combinerà le colonne Cognome
, ID_dipartimento
e Nome_dipartimento
in un'unica riga per la tabella risultante.
Esempio di INNER JOIN
in forma esplicita:
SELECT *
FROM Impiegati
INNER JOIN Dipartimenti
ON Impiegati.ID_dipartimento = Dipartimenti.ID_dipartimento
che equivale a:
SELECT *
FROM Impiegati, Dipartimenti
WHERE Impiegati.ID_dipartimento = Dipartimenti.ID_dipartimento
Risultato della query di INNER JOIN
:
Impiegati.Cognome | Impiegati.ID_dipartimento | Dipartimenti.Nome_dipartimento | Dipartimenti.ID_dipartimento |
---|---|---|---|
Santoro | 34 | Risorse umane | 34 |
Bianchi | 33 | Tecnico | 33 |
Monti | 34 | Risorse umane | 34 |
Mancini | 33 | Tecnico | 33 |
Rossi | 31 | Vendite | 31 |
Nota: l'impiegato Grassi
e il dipartimento Promozione
non sono presenti in quanto l'impiegato Grassi
ha un NULL
mentre Promozione
non compare in nessun impiegato. A volte come risultato finale si desidera avere anche i record che non hanno corrispondenza: in tal caso è possibile usare la query di tipo OUTER JOIN
.
Equi-join
[modifica | modifica wikitesto]La equi-join, noto come "l'unica operazione ammissibile", ha un particolare tipo di comparatore, detto theta join, che utilizza come metodo di verifica, solamente l'uguaglianza matematica come regola di confronto. Usare altri operatori di confronto (come ad esempio <
) squalifica la join come equi-join. La query riportata di seguito utilizza una equi-join:
SELECT *
FROM Impiegati
INNER JOIN Dipartimenti
ON Impiegati.ID_dipartimento = Dipartimenti.ID_dipartimento
SQL fornisce una scorciatoia per definire le equi-joins, attraverso la parola riservata USING
SELECT *
FROM Impiegati
INNER JOIN Dipartimenti
USING (ID_dipartimento)
La keyword USING
è supportata da Microsoft SQL Server Management Studio, MySQL, Oracle, PostgreSQL, SQLite, e DB2/400.
Natural join
[modifica | modifica wikitesto]Una NATURAL JOIN
offre ulteriori specializzazioni di equi-join. Solitamente la JOIN
confronta colonne di tabelle diverse che hanno lo stesso nome. La NATURAL JOIN
fa proprio questo.
Nell'esempio che segue viene riportata la notazione NATURAL JOIN
equivalente alla prima INNER JOIN
definita:
SELECT *
FROM Impiegati
NATURAL JOIN Dipartimenti
ID_dipartimento | Impiegati.Cognome | Dipartimenti.Nome_dipartimento |
---|---|---|
34 | Monti | Risorse umane |
33 | Bianchi | Tecnico |
34 | Santoro | Risorse umane |
33 | Mancini | Tecnico |
31 | Rossi | Vendite |
Cross join
[modifica | modifica wikitesto]Una CROSS JOIN
, cartesian join o product fornisce le basi (le infrastrutture informatiche) attraverso cui tutti i tipi di INNER JOIN
operano. Il risultato di una CROSS JOIN
è il prodotto cartesiano di tutte le righe delle tabelle che concorrono alla query di join. È come dire che stiamo facendo una INNER JOIN
senza impostare la regola di confronto o in cui la regola di confronto ritorna sempre vero.
Date le due tabelle di partenza e , la cross join si scrive × .
Esempio di CROSS JOIN
esplicito:
SELECT *
FROM Impiegati CROSS JOIN Dipartimenti
Altro esempio implicito di CROSS JOIN
:
SELECT *
FROM Impiegati, Dipartimenti;
Impiegati.Cognome | Impiegati.ID_dipartimento | Dipartimenti.Nome_dipartimento | Dipartimenti.ID_dipartimento |
---|---|---|---|
Rossi | 31 | Vendite | 31 |
Bianchi | 33 | Vendite | 31 |
Mancini | 33 | Vendite | 31 |
Monti | 34 | Vendite | 31 |
Santoro | 34 | Vendite | 31 |
Grassi | NULL |
Vendite | 31 |
Rossi | 31 | Tecnico | 33 |
Bianchi | 33 | Tecnico | 33 |
Mancini | 33 | Tecnico | 33 |
Monti | 34 | Tecnico | 33 |
Santoro | 34 | Tecnico | 33 |
Grassi | NULL |
Tecnico | 33 |
Rossi | 31 | Risorse umane | 34 |
Bianchi | 33 | Risorse umane | 34 |
Mancini | 33 | Risorse umane | 34 |
Monti | 34 | Risorse umane | 34 |
Santoro | 34 | Risorse umane | 34 |
Grassi | NULL |
Risorse umane | 34 |
Rossi | 31 | Promozione | 35 |
Bianchi | 33 | Promozione | 35 |
Mancini | 33 | Promozione | 35 |
Monti | 34 | Promozione | 35 |
Santoro | 34 | Promozione | 35 |
Grassi | NULL |
Promozione | 35 |
Outer join
[modifica | modifica wikitesto]Una OUTER JOIN
non richiede che ci sia corrispondenza esatta tra le righe di due tabelle. La tabella risultante da una outer join trattiene tutti quei record che non hanno alcuna corrispondenza tra le tabelle. Le OUTER JOIN
si suddividono in LEFT OUTER JOIN
, RIGHT OUTER JOIN
, e FULL OUTER JOIN
, in base a quale sia la tabella di cui intendiamo trattenere i valori in caso di mancata corrispondenza della regola di confronto da (sinistra, destra, o entrambi). In questo caso left (sinistra) e right (destra) si riferiscono ai due lati della keyword JOIN
.
Nota sulle clausole WHERE e ON
[modifica | modifica wikitesto]Si sottolinea come esista un ordine di esecuzione tra le condizioni specificate nella WHERE
e quelle presenti nella ON
.
Specificatamente le clausole presenti nella ON
sono valutate anteriormente all'esecuzione della JOIN
mentre le clausole nella where sono valutate successivamente all'esecuzione della JOIN
.
Left outer join
[modifica | modifica wikitesto]Il risultato di una query LEFT OUTER JOIN
(o semplicemente LEFT JOIN
) per le tabelle e contiene sempre tutti i record della tabella di sinistra (left) , mentre vengono estratti dalla tabella di destra (right) solamente le righe che trovano corrispondenza nella regola di confronto della join. Questo significa che se la clausola ON
trova zero righe in , la JOIN
mostrerà una riga risultante con valore NULL
in tutte le colonne corrispondenti al risultato per le colonne di .
Esempio di una left outer join:
SELECT *
FROM Impiegati LEFT OUTER JOIN Dipartimenti
ON Impiegati.ID_dipartimento = Dipartimenti.ID_dipartimento
Impiegati.Cognome | Impiegati.ID_dipartimento | Dipartimenti.Nome_dipartimento | Dipartimenti.ID_dipartimento |
---|---|---|---|
Bianchi | 33 | Tecnico | 33 |
Rossi | 31 | Vendite | 31 |
Santoro | 34 | Risorse umane | 34 |
Monti | 34 | Risorse umane | 34 |
Grassi | NULL |
NULL |
NULL
|
Mancini | 33 | Tecnico | 33 |
Right outer join
[modifica | modifica wikitesto]Una RIGHT OUTER JOIN
(o RIGHT JOIN
) semplicemente ricalca il funzionamento della LEFT OUTER JOIN
, ma invertendo l'ordine delle tabelle interessate.
Il risultato di una query RIGHT OUTER JOIN
per le tabelle e contiene sempre tutti i record della tabella di destra (right) , mentre vengono estratti dalla tabella di sinistra (left) solamente le righe che trovano corrispondenza nella regola di confronto della JOIN
. Questo significa che se la clausola ON
trova zero righe in , la JOIN
mostrerà una riga risultante con valore NULL
in tutte le colonne corrispondenti al risultato per le colonne di .
Esempio di una RIGHT OUTER JOIN
:
SELECT *
FROM Impiegati RIGHT OUTER JOIN Dipartimenti
ON Impiegati.ID_dipartimento = Dipartimenti.ID_dipartimento
Impiegati.Cognome | Impiegati.ID_dipartimento | Dipartimenti.Nome_dipartimento | Dipartimenti.ID_dipartimento |
---|---|---|---|
Monti | 34 | Risorse umane | 34 |
Bianchi | 33 | Tecnico | 33 |
Santoro | 34 | Risorse umane | 34 |
Mancini | 33 | Tecnico | 33 |
Rossi | 31 | Vendite | 31 |
NULL |
NULL |
Promozione | 35 |
In pratica sono utilizzate maggiormente le query di LEFT OUTER JOIN
rispetto a quelle di RIGHT OUTER JOIN
, ma possono verificarsi rari casi in cui in query molto complesse ci sia la necessità di utilizzare contemporaneamente il criterio di LEFT OUTER JOIN
e di RIGHT OUTER JOIN
.
Lo stesso risultato della precedente RIGHT OUTER JOIN
si può ripetere usando il tipo LEFT OUTER JOIN
:
SELECT *
FROM Dipartimenti LEFT OUTER JOIN Impiegati
ON Impiegati.ID_dipartimento = Dipartimenti.ID_dipartimento
Full outer join
[modifica | modifica wikitesto]Una FULL OUTER JOIN
combina i risultati delle due tabelle e tenendo conto di tutte le righe delle tabelle, anche di quelle che non hanno corrispondenza tra di loro.
Il risultato di una query FULL OUTER JOIN
per le tabelle e contiene sempre tutti i record della tabella di sinistra (left) , estraendo dalla tabella di destra (right) solamente le righe che trovano corrispondenza nella regola di confronto della join; inoltre verranno estratti tutti i record della tabella di sinistra (left) che non trovano corrispondenza nella tabella di destra (right) impostando a NULL
i valori di tutte le colonne della tabella e tutti i record della tabella di destra (right) che non trovano corrispondenza nella tabella di sinistra (left) impostando a NULL
i valori di tutte le colonne della tabella .
Esempio di una FULL OUTER JOIN
:
SELECT *
FROM Impiegati
FULL OUTER JOIN Dipartimenti
ON Impiegati.ID_dipartimento = Dipartimenti.ID_dipartimento
Impiegati.Cognome | Impiegati.ID_dipartimento | Dipartimenti.Nome_dipartimento | Dipartimenti.ID_dipartimento |
---|---|---|---|
Monti | 34 | Risorse umane | 34 |
Bianchi | 33 | Tecnico | 33 |
Santoro | 34 | Risorse umane | 34 |
Grassi | NULL |
NULL |
NULL
|
Mancini | 33 | Tecnico | 33 |
Rossi | 31 | Vendite | 31 |
NULL |
NULL |
Promozione | 35 |
Alcuni database (come per esempio MySQL) non supportano direttamente questa funzionalità, ma la si può emulare attraverso la combinazione di LEFT OUTER JOIN
e RIGHT OUTER JOIN
per mezzo della parola riservata UNION
.
La creazione di una query di FULL OUTER JOIN
si realizzerà come segue:
SELECT *
FROM Impiegati
LEFT JOIN Dipartimenti
ON Impiegati.ID_dipartimento = Dipartimenti.ID_dipartimento
UNION
SELECT *
FROM Impiegati
RIGHT JOIN Dipartimenti
ON Impiegati.ID_dipartimento = Dipartimenti.ID_dipartimento
WHERE Impiegati.ID_dipartimento IS NULL
Allo stesso modo senza utilizzare nemmeno la query di RIGHT OUTER JOIN
:
SELECT Impiegati.*, Dipartimenti.*
FROM Impiegati
LEFT JOIN Dipartimenti
ON Impiegati.ID_dipartimento = Dipartimenti.ID_dipartimento
UNION
SELECT Impiegati.*, Dipartimenti.*
FROM Dipartimenti
LEFT JOIN Impiegati
ON Impiegati.ID_dipartimento = Dipartimenti.ID_dipartimento
WHERE Impiegati.ID_dipartimento IS NULL
Self-join
[modifica | modifica wikitesto]La self-join serve a unire una tabella con se stessa.
Voci correlate
[modifica | modifica wikitesto]Altri progetti
[modifica | modifica wikitesto]- Wikimedia Commons contiene immagini o altri file sulla join
Collegamenti esterni
[modifica | modifica wikitesto]- (EN) Denis Howe, join, in Free On-line Dictionary of Computing. Disponibile con licenza GFDL
- Introduzione alle JOIN (nella knowledgebase di AskMonty), su kb.askmonty.org. URL consultato il 18 ottobre 2022 (archiviato dall'url originale il 20 dicembre 2012).