Join SQL (in italiano: "giunzione") è un'o­pe­ra­zio­ne nei database re­la­zio­na­li che permette di in­ter­ro­ga­re più tabelle di database. I join combinano i dati me­mo­riz­za­ti in diverse tabelle e li re­sti­tui­sco­no in forma filtrata in una tabella dei risultati.

Il principio del join SQL si basa sul­l'o­mo­ni­ma ope­ra­zio­ne algebrica re­la­zio­na­le, cioè una com­bi­na­zio­ne derivata da un prodotto car­te­sia­no e da una selezione. L'utente determina quali dati delle tabelle di output vengono tra­sfe­ri­ti alla tabella dei risultati se­le­zio­nan­do un tipo di join e definendo una con­di­zio­ne di selezione.

Consiglio

Questo articolo sui join SQL pre­sup­po­ne la co­no­scen­za di de­ter­mi­na­ti concetti legati ai database re­la­zio­na­li, in par­ti­co­la­re per quanto riguarda le relazioni, le tuple, gli attributi o le chiavi. Trovate un'in­tro­du­zio­ne nel nostro articolo di base sui database re­la­zio­na­li.

Vi pre­sen­tia­mo le basi ma­te­ma­ti­che dei join SQL, con­fron­tia­mo diversi tipi di join e vi mostriamo come im­ple­men­tar­li nelle query di database tramite SQL uti­liz­zan­do esempi pratici.

Come fun­zio­na­no i join SQL?

Il principio di base dei join SQL può essere il­lu­stra­to derivando il fun­zio­na­men­to del database dalle sue sot­to­pe­ra­zio­ni. Ogni join si basa sulle seguenti ope­ra­zio­ni di algebra re­la­zio­na­le:

  • Prodotto car­te­sia­no
  • Selezione

Il prodotto car­te­sia­no

Il prodotto car­te­sia­no (o unione in­cro­cia­ta) è un'o­pe­ra­zio­ne di teoria degli insiemi in cui due o più insiemi sono collegati tra loro. Nel modello di database re­la­zio­na­le, il prodotto car­te­sia­no viene uti­liz­za­to per collegare i set di tuple sotto forma di tabelle. Il risultato di questa ope­ra­zio­ne è di nuovo un insieme di tuple ordinate, dove ogni tupla è composta da un elemento di ogni set iniziale.

Nel­l'al­ge­bra re­la­zio­na­le, il segno di mol­ti­pli­ca­zio­ne (×) viene uti­liz­za­to come operatore per il prodotto car­te­sia­no.

Di seguito un esempio:

il prodotto car­te­sia­no A × B dei due set A = {x, y, z} e B = {1, 2, 3} è:

A × B = {(x,1), (x,2), (x,3), (y,1), (y,2), (y,3), (z,1), (z,2), (z,3)}

Il calcolo si può chiarire grazie al grafico seguente:

La sequenza di for­ma­zio­ne delle coppie deve essere ri­spet­ta­ta. Ad esempio, il prodotto car­te­sia­no A × B non cor­ri­spon­de alla stessa quantità del prodotto car­te­sia­no B × A.

A × B = {(x,1), (x,2), (x,3), (y,1), (y,2), (y,3), (z,1), (z,2), (z,3)}

B × A = {(1,x), (1,y), (1,z), (2,x), (2,y), (2,z), (3,x), (3,y), (3,z)}

Nella ter­mi­no­lo­gia SQL, un'o­pe­ra­zio­ne in cui il prodotto car­te­sia­no è formato da due tabelle di database è de­no­mi­na­ta cross join. In pratica, le cross join sono raramente uti­liz­za­te a causa del risultato non filtrato.

La selezione

La selezione è un'o­pe­ra­zio­ne di algebra re­la­zio­na­le che consente di se­le­zio­na­re spe­ci­fi­che tuple da un set iniziale e di inviarle come risultato. Un'e­spres­sio­ne di confronto può essere usata per de­ter­mi­na­re quali tuple sono incluse nel set di risultati. Il risultato della selezione è quindi un insieme di tuple che sod­di­sfa­no la con­di­zio­ne di selezione definita nel­l'e­spres­sio­ne di confronto. Come operatore viene uti­liz­za­ta la lettera greca Sigma (σ). L'o­pe­ra­zio­ne è descritta di seguito:

σF (R)

Il se­gna­po­sto "F" cor­ri­spon­de al­l'e­spres­sio­ne di confronto, una formula di predicati logici che de­fi­ni­sco­no la con­di­zio­ne di selezione. R sta per il set di dati da se­le­zio­na­re. In al­ter­na­ti­va, è possibile uti­liz­za­re la notazione lineare R[F].

Per la for­mu­la­zio­ne delle con­di­zio­ni di selezione sono di­spo­ni­bi­li i soliti operatori di confronto: ad esempio, uguale (=), maggiore (>) o minore (<).

Spie­ghia­mo la selezione uti­liz­zan­do un esempio che abbiamo già in­tro­dot­to nel testo di base del modello di database re­la­zio­na­le. La tabella seguente riporta i dati personali fittizi che un'a­zien­da avrebbe potuto inserire per i propri di­pen­den­ti. Per ogni col­la­bo­ra­to­re, vengono spe­ci­fi­ca­ti l'id personale (c_id), ge­ne­ra­li­tà (cognome, nome), il codice fiscale (cf), l'in­di­riz­zo (via, CAP, città) e l'auto aziendale assegnata (auto_id).

Tabella: col­la­bo­ra­to­ri

c_id cognome nome cf via n. CAP città auto_id
1 Bianchi Maria BNCMRA55F59F500S Via Roma 1 11111 Roma 3
2 Rossi Giada RSSGDI97G54B243L Via Matteotti 2 22222 Genova 1
3 Padovan Gianluca PDVGLC55M21L424T Via F.lli Cervi 3 33333 Gela 1
4 Terragna Eli­sa­bet­ta TRRLBT32R56C352Z Via Quasimodo 4 44444 Novara 2

Se vogliamo se­le­zio­na­re la tabella "col­la­bo­ra­to­ri" in modo tale che vengano vi­sua­liz­za­ti solo i di­pen­den­ti che guidano l'auto aziendale con auto_id 1, possiamo procedere come segue:

σauto_id=1(col­la­bo­ra­to­ri)

Re­cu­pe­ria­mo sem­pli­ce­men­te le tuple dove il valore nella colonna auto_id è uguale a 1.

Il risultato cor­ri­spon­de alla seguente tabella.

Tabella: col­la­bo­ra­to­ri (se­le­zio­na­ta)

c_id nome cognome cf via n. CAP città auto_id
2 Rossi Giada RSSGDI97G54B243L Via Matteotti 2 22222 Genova 1
3 Padovan Gianluca PDVGLC55M21L424T Via F.lli Cervi 3 33333 Gela 1

Nel lin­guag­gio SQL del database, le con­di­zio­ni di selezione sono definite uti­liz­zan­do il comando WHERE.

SELECT * FROM collaboratori WHERE collaboratori.auto_id = 1;

Se una tupla soddisfa la con­di­zio­ne auto_id = 1, i valori di tutte le colonne devono essere vi­sua­liz­za­ti per questa tupla.

N.B.

L'a­ste­ri­sco (*) rap­pre­sen­ta tutte le colonne di una tabella nella sintassi SQL.

Com­bi­na­zio­ne di prodotto car­te­sia­no e selezione

Tutti i comuni tipi di join combinano il prodotto car­te­sia­no a una con­di­zio­ne di selezione. Al fine di spiegare tale ope­ra­zio­ne di database, per motivi di chiarezza, riduciamo la tabella "col­la­bo­ra­to­ri" a quattro colonne. Inoltre, in­tro­du­cia­mo la tabella "auto", in cui sono me­mo­riz­za­te in­for­ma­zio­ni det­ta­glia­te sul parco veicoli del­l'a­zien­da.

Entrambe le tabelle sono collegate tra loro da una relazione a chiave esterna. La chiave primaria della tabella "auto" (auto_id) funge da chiave esterna nella tabella "col­la­bo­ra­to­ri".

Tabella: col­la­bo­ra­to­ri

c_id cognome nome auto_id
1 Bianchi Maria 3
2 Rossi Giada 1
3 Padovan Gianluca 1
4 Terragna Eli­sa­bet­ta 2

Tabella: auto

auto_id marca modello targa anno di co­stru­zio­ne revisione
1 VW Caddy B KH 778 2016 18.12.2018
2 Opel Astra B PO 654 2010 12.08.2019
3 BMW X6 B MW 780 2017 01.09.2018
N.B.

L'e­ster­na­liz­za­zio­ne di in­for­ma­zio­ni nelle diverse tabelle di database è un concetto di base del modello di database re­la­zio­na­le. I vantaggi di una struttura simile di database così come la sua im­ple­men­ta­zio­ne sono discussi in un ulteriore articolo sulla nor­ma­liz­za­zio­ne dei database re­la­zio­na­li.

Se si desidera unire le due tabelle e se­le­zio­na­re con­tem­po­ra­nea­men­te le relative tuple, è possibile combinare le ope­ra­zio­ni del database pre­ce­den­te­men­te in­tro­dot­te:

σauto_id=auto_id(col­la­bo­ra­to­ri × auto)

Per primo viene formato il prodotto car­te­sia­no col­la­bo­ra­to­ri × auto. Il risultato (in­ter­me­dio) è una cross join, cioè una tabella dei risultati in cui ogni tupla della tabella "col­la­bo­ra­to­ri" è combinata con ogni tupla della tabella "auto".

Tabella: prodotto car­te­sia­no "col­la­bo­ra­to­ri" × "auto"

c_id cognome nome col­la­bo­ra­to­ri.auto_id auto.auto_id marca modello targa anno di co­stru­zio­ne revisione
1 Bianchi Maria 3 1 VW Caddy B KH 778 2016 18.12.2018
1 Bianchi Maria 3 2 Opel Astra B PO 654 2010 12.08.2019
1 Bianchi Maria 3 3 BMW X6 B MW 780 2017 01.09.2018
2 Rossi Giada 1 1 VW Caddy B KH 778 2016 18.12.2018
2 Rossi Giada 1 2 Opel Astra B PO 654 2010 12.08.2019
2 Rossi Giada 1 3 BMW X6 B MW 780 2017 01.09.2018
3 Padovan Gianluca 1 1 VW Caddy B KH 778 2016 18.12.2018
3 Padovan Gianluca 1 2 Opel Astra B PO 654 2010 12.08.2019
3 Padovan Gianluca 1 3 BMW X6 B MW 780 2017 01.09.2018
4 Terragna Eli­sa­bet­ta 2 1 VW Caddy B KH 778 2016 18.12.2018
4 Terragna Eli­sa­bet­ta 2 2 Opel Astra B PO 654 2010 12.08.2019
4 Terragna Eli­sa­bet­ta 2 3 BMW X6 B MW 780 2017 01.09.2018

Poi vengono se­le­zio­na­te solo quelle tuple dove il record auto_id della tabella "auto" cor­ri­spon­de al record auto_id della tabella "col­la­bo­ra­to­ri". La con­di­zio­ne di selezione è che la chiave esterna della tabella "col­la­bo­ra­to­ri" cor­ri­spon­da alla chiave primaria della tabella "auto".

Il risultato (finale) è una tabella che unisce entrambe le tabelle di output senza ri­don­dan­ze.

Tabella: join tra "col­la­bo­ra­to­ri" e "auto"

c_id cognome nome col­la­bo­ra­to­ri.auto_id auto.auto_id marca modello targa anno di co­stru­zio­ne revisione
1 Bianchi Maria 3 3 BMW X6 B MW 780 2017 01.09.2018
2 Rossi Giada 1 1 VW Caddy B KH 778 2016 18.12.2018
3 Padovan Gianluca 1 1 VW Caddy B KH 778 2016 18.12.2018
4 Terragna Eli­sa­bet­ta 2 2 Opel Astra B PO 654 2010 12.08.2019

I join combinano entrambe le ope­ra­zio­ni in un'unica ope­ra­zio­ne, in quanto com­bi­na­zio­ne del prodotto car­te­sia­no e della suc­ces­si­va selezione. Il simbolo "bow tie" (⋈) viene uti­liz­za­to come operatore.

Si applica pertanto:

σauto_id=auto_id(col­la­bo­ra­to­ri × auto) := col­la­bo­ra­to­ri⋈auto_id=auto_idauto

L'o­pe­ra­zio­ne σauto_id=auto_id(col­la­bo­ra­to­ri × auto) cor­ri­spon­de a un join tra le tabelle "col­la­bo­ra­to­ri" e "auto" con il pre­re­qui­si­to auto_id=auto_id.

Tra­sfe­ri­ta alla sintassi SQL, l'o­pe­ra­zio­ne qui sopra cor­ri­spon­de­reb­be alla seguente di­chia­ra­zio­ne:

SELECT * FROM collaboratori INNER JOIN auto ON collaboratori.auto_id = auto.auto_id;

L'inner join è uno dei più im­por­tan­ti join uti­liz­za­ti per le query al database. A volte, tuttavia, per ottenere il risultato de­si­de­ra­to sono necessari tipi speciali di join.

Tipi di join SQL

Nel modello di database re­la­zio­na­le, vengono uti­liz­za­ti diversi tipi di join SQL che con­sen­to­no di eseguire query uti­liz­zan­do un insieme di tabelle di database. Il pre­re­qui­si­to per fare ciò è che le tabelle se­le­zio­na­te siano collegate tra loro uti­liz­zan­do relazioni a chiave esterna.

I tipi di join più im­por­tan­ti sono i seguenti:

  • inner join: una inner join è una forma filtrata della cross join in cui solo le tuple di entrambe le tabelle di output che sod­di­sfa­no la con­di­zio­ne di selezione definita dal­l'u­ten­te vengono unite insieme nel risultato impostato.
  • outer join: una outer join è un'e­sten­sio­ne del­l'in­ner join. L'insieme dei risultati di una outer join contiene le tuple di entrambe le tabelle di output che sod­di­sfa­no la con­di­zio­ne di selezione definita dal­l'u­ten­te, così come tutte le tuple rimanenti della prima tabella, della seconda tabella o di entrambe le tabelle. Le outer join sono im­ple­men­ta­te di con­se­guen­za come left outer join, right outer join o full outer join.
Consiglio

Trovate una de­scri­zio­ne det­ta­glia­ta delle inner join e delle outer join negli articoli di ap­pro­fon­di­men­to ai tipi di join.

Le dif­fe­ren­ze tra le inner join e le diverse varianti del­l'ou­ter join possono essere il­lu­stra­te da diagrammi. Il grafico seguente illustra i tipi di join pre­sen­ta­ti:

In­di­pen­den­te­men­te dalla di­stin­zio­ne tra inner join e outer join, i join SQL possono anche essere clas­si­fi­ca­ti nei seguenti tipi di join:

  • EQUI JOIN
  • NON EQUI JOIN
  • SELF JOIN

Le inner join e le outer join possono essere im­ple­men­ta­te come equi join e non equi join. Tutti gli esempi di join pre­sen­ta­ti finora sono equi join. Le equi join sono ca­rat­te­riz­za­te dal fatto che per­met­to­no solo il segno uguale come operatore di confronto (=). La con­di­zio­ne di selezione di una equi join è quindi sempre l'u­gua­glian­za dei valori delle colonne. In linea di principio, i join (così come la selezione nel­l'al­ge­bra re­la­zio­na­le) non sono però limitati al­l'u­gua­glian­za delle colonne. Possibili operatori di confronto sono:

Operatori di confronto Si­gni­fi­ca­to
= uguale
< minore
> maggiore
minore o uguale
maggiore o uguale
<> disuguale
!= disuguale

A partire da SQL 92 il lin­guag­gio del database offre una notazione ab­bre­via­ta per equi join con la parola chiave USING. Tuttavia, ciò pre­sup­po­ne che le colonne in­te­res­sa­te abbiano lo stesso nome, anche se non è sempre così.

L'esempio seguente mostra due diverse di­chia­ra­zio­ni SQL che portano allo stesso risultato. Nella prima di­chia­ra­zio­ne, l'o­pe­ra­zio­ne join è espli­ci­ta­men­te definita uti­liz­zan­do la parola chiave ON. Per la seconda di­chia­ra­zio­ne, usiamo la notazione ab­bre­via­ta con la parola chiave USING.

SELECT * FROM collaboratori INNER JOIN auto ON collaboratori.auto_id = auto.auto_id;
SELECT * FROM collaboratori INNER JOIN auto USING auto_id;

Le non equi join, invece, escludono le ope­ra­zio­ni basate sul­l'u­gua­glian­za delle colonne. Sono quindi con­sen­ti­te tutte le ope­ra­zio­ni di confronto ad eccezione del segno uguale (=).

N.B.

Visto che le relazioni nei database re­la­zio­na­li vengono definiti so­li­ta­men­te tramite l'u­gua­glian­za delle chiavi primarie ed esterne, le non equi join nel modello di database re­la­zio­na­li hanno un'im­por­tan­za se­con­da­ria. Non in ultimo perché queste, come le cross join, portano spesso a set di risultati.

Infine, una self join è una forma speciale di join SQL in cui una tabella di database è collegata a se stessa. In linea di principio, qualsiasi tipo di join può essere eseguito come self join.

Se due tabelle sono collegate da colonne con lo stesso nome, si parla di natural join. Una natural join è im­ple­men­ta­ta di default come inner join uti­liz­zan­do la parola chiave omonima. Tuttavia, le natural join non sono fissate a questo tipo di join. È possibile anche una natural left outer join o una natural right outer join.

Poiché le natural join sono collegate uti­liz­zan­do colonne con lo stesso nome, i ri­spet­ti­vi valori non vengono emessi due volte nel set di risultati, ma vengono uniti per formare una colonna comune. Trovate esempi di natural join negli articoli di ap­pro­fon­di­men­to su inner join e outer join.

Vai al menu prin­ci­pa­le