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: INNERJOIN, FULLJOIN, LEFTJOIN e RIGHTJOIN, alle quali diversi DBMS aggiungono CROSSJOIN. In alcuni casi è possibile che una tabella possa essere combinata con se stessa, in questo caso si parlerà di self-join.
Tabelle di esempio
Tutti gli esempi che verranno riportati di seguito faranno uso delle seguenti due tabelle:
Tabella Impiegati
Cognome
ID_dipartimento
Rossi
31
Bianchi
33
Mancini
33
Santoro
34
Monti
34
Grassi
NULL
Tabella Dipartimenti
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).
Una INNERJOIN 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 INNERJOIN è 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.
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 OUTERJOIN.
Equi-join
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:
Una NATURALJOIN offre ulteriori specializzazioni di equi-join. Solitamente la JOIN confronta colonne di tabelle diverse che hanno lo stesso nome. La NATURALJOIN fa proprio questo.
Nell'esempio che segue viene riportata la notazione NATURALJOIN equivalente alla prima INNERJOIN definita:
SELECT*FROMImpiegatiNATURALJOINDipartimenti
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
Immagine che rappresenta la CROSSJOIN di due tabelle
Una CROSSJOIN, cartesian join o product fornisce le basi (le infrastrutture informatiche) attraverso cui tutti i tipi di INNERJOIN operano. Il risultato di una CROSSJOIN è il prodotto cartesiano di tutte le righe delle tabelle che concorrono alla query di join. È come dire che stiamo facendo una INNERJOIN 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 CROSSJOIN esplicito:
SELECT*FROMImpiegatiCROSSJOINDipartimenti
Altro esempio implicito di CROSSJOIN:
SELECT*FROMImpiegati,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
Una OUTERJOIN 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 OUTERJOIN si suddividono in LEFTOUTERJOIN, RIGHTOUTERJOIN, e FULLOUTERJOIN, 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 keywordJOIN.
Nota sulle clausole WHERE e ON
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.
Il risultato di una query LEFTOUTERJOIN (o semplicemente LEFTJOIN) 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 .
Una RIGHTOUTERJOIN (o RIGHTJOIN) semplicemente ricalca il funzionamento della LEFTOUTERJOIN, ma invertendo l'ordine delle tabelle interessate.
Il risultato di una query RIGHTOUTERJOIN 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 .
In pratica sono utilizzate maggiormente le query di LEFTOUTERJOIN rispetto a quelle di RIGHTOUTERJOIN, ma possono verificarsi rari casi in cui in query molto complesse ci sia la necessità di utilizzare contemporaneamente il criterio di LEFTOUTERJOIN e di RIGHTOUTERJOIN.
Lo stesso risultato della precedente RIGHTOUTERJOIN si può ripetere usando il tipo LEFTOUTERJOIN:
Una FULLOUTERJOIN 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 FULLOUTERJOIN 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 .
Alcuni database (come per esempio MySQL) non supportano direttamente questa funzionalità, ma la si può emulare attraverso la combinazione di LEFTOUTERJOIN e RIGHTOUTERJOIN per mezzo della parola riservata UNION.
La creazione di una query di FULLOUTERJOIN si realizzerà come segue: