Torna all'elenco degli articoli Articoli
Tempo di lettura: 10 minuti

Come unire due volte la stessa tabella

La JOIN è una delle istruzioni più comuni in SQL. Come forse sapete, viene utilizzata per unire e combinare i dati di due o più tabelle in un unico insieme di dati. In questo articolo parleremo di tipi speciali di join, in cui si unisce due volte la stessa tabella, compreso il join di una tabella a se stessa, noto anche come self join. Quando e perché è necessario farlo? Come si scrive in SQL? Scopriamolo.

Gemelli

Unioni: Un rapido ripasso

Probabilmente conoscete i join in SQL. Abbiamo due tabelle, A e B, e le uniamo utilizzando una colonna comune a entrambe. Ecco un esempio:

Tabelle

Abbiamo due tabelle: customer e citycon una colonna comune denominata city_id.

Ora, se si desidera unire le due tabelle per ottenere i nomi delle città dei clienti, è possibile farlo con un join di questo tipo:

select customer.customer_id,
     customer.firstname,
     customer.lastname,
     customer.birthdate,
     customer.spouse_id,
     customer.city_id,
     city.name as city_name
from customer 
join city 
on customer.city_id = city.city_id;

In questa istruzione JOIN, vengono abbinati i record di customer e city in base a una chiave (city_id). Si recuperano tutte e 6 le colonne della tabella customer e una colonna, name, dalla tabella city dalla tabella. Esistono diversi tipi di join in SQL; questo esempio fa un INNER JOIN.

Non intendo approfondire la sintassi di JOIN in questa sede. Per saperne di più, date un'occhiata al nostro corso interattivo sulle giunzioni SQL che potete trovare su LearnSQL.it.

Il risultato di questa unione sarà una tabella con tutti i 6 campi della tabella customer più un campo aggiuntivo dalla tabella city della tabella:

customer_idfirstnamelastnamebirthdatespouse_idcity_idcity_name
1JohnMayer1983‑05‑1221London
2MaryMayer1990-07-3011London
3LisaRoss1989-04-1556Oxford
4AnnaTimothy1988-12-2664Leeds
5TimRoss1957-08-1536Oxford
6SteveDonell1967-07-0944Leeds
7DonnaTrapp1978-06-2302Manchester

Unire più volte la stessa tabella

Ora che abbiamo fatto un rapido ripasso, esaminiamo le unioni più complesse.

A volte è necessario unire più volte la stessa tabella. In genere, si tratta di aggiungere una o più colonne a un set di risultati della stessa tabella, ma a record diversi o per colonne diverse. Esamineremo due scenari di questo tipo: l'unione di una tabella a se stessa e l'unione di tabelle con relazioni multiple.

Self Join: Unire una tabella a se stessa

La self join è un caso speciale di join. Invece di unire due tabelle diverse, si unisce una tabella a se stessa. Perché si vuole fare questo?

Nell'esempio precedente, volevamo aggiungere una colonna della tabella city il nome della città, alla tabella customer tabella. Quindi, abbiamo unito due tabelle diverse. Eseguire un self join significa, per esempio, unire la tabella customer a se stessa.

Ecco la customer come promemoria:

customer_idfirstnamelastnamebirthdatespouse_id
1JohnMayer1983-05-122
2MaryMayer1990-07-301
3LisaRoss1989-04-155
4AnnaTimothy1988-12-266
5TimRoss1957-08-153
6SteveDonell1967-07-094
7DonnaTrapp1978-06-23.

La colonna spouse_id contiene l'indirizzo customer_id del coniuge del cliente. Ad esempio, i clienti 1 e 2 (John e Mary) sono coniugi tra loro, i clienti 3 e 5 (Lisa e Tim) sono coniugi tra loro e così via. Possiamo aggiungere il nome e il cognome del coniuge a ogni record della tabella. customer tabella. Per fare questo, dobbiamo eseguire un self join, cioè unire la tabella customer a se stessa:

select cust.customer_id,
      cust.firstname,
      cust.lastname,
      cust.birthdate,
      cust.spouse_id,
      spouse.firstname as spouse_firstname,
      spouse.lastname as spouse_lastname
from customer cust 
join customer spouse
on cust.spouse_id = spouse.customer_id;

Quando si esegue questo codice, il risultato è il seguente:

customer_idfirstnamelastnamebirthdatespouse_idspouse_firstnamespouse_lastname
1JohnMayer1983‑05‑122MaryMayer
2MaryMayer1990-07-301JohnMayer
3LisaRoss1989-04-155TimRoss
4AnnaTimothy1988-12-266SteveDonell
5TimRoss1957-08-153LisaRoss
6SteveDonell1967-07-094AnnaTimothy

Dopo aver visto un esempio di utilizzo delle self join, esaminiamo la sintassi SQL.

Sintassi del self join

La sintassi della self join è molto simile a quella di qualsiasi altro tipo di join. Ecco il codice del nostro esempio di self join:

select cust.customer_id,
      cust.firstname,
      cust.lastname,
      cust.birthdate,
      cust.spouse_id,
      spouse.firstname as spouse_firstname,
      spouse.lastname as spouse_lastname
from customer cust
join customer spouse
on cust.spouse_id = spouse.customer_id;

Si tratta di un'istruzione JOIN in cui la tabella customer viene utilizzata due volte.

Le informazioni sul coniuge, come il suo nome, sono memorizzate nella stessa tabella come un cliente separato con il proprio customer_id. Poiché spouse_id contiene il customer_id nome del coniuge, dobbiamo unire la tabella con se stessa per ottenere il nome del coniuge.

Si può pensare a un self join come a un join tra due copie della stessa tabella. Per ogni record con un valore non nullo in spouse_id, cerchiamo il valore di customer_id che corrisponde. Quando troviamo una corrispondenza, le colonne firstname e lastname vengono aggiunte alla tabella risultante.

Gli alias delle tabelle sono necessari in un self join. Il codice non funziona senza di essi, poiché non saprebbe a quale copia della tabella ci si riferisce. Qui, sto usando gli alias cust e spouse.

Subito prima della parola chiave FROM, scegliamo le colonne che vogliamo mantenere nella tabella risultante. Dobbiamo usare gli alias della tabella per recuperare le colonne (cust.firstname, cust.lastname, spouse.firstname, ecc.). Manteniamo cinque colonne dalla tabella customer e aggiungiamo dalla stessa tabella due colonne che contengono il nome del coniuge.

Si tratta di una join interna, ma si può usare qualsiasi tipo di join: LEFT JOIN, RIGHT JOIN, CROSS JOIN, ecc. Nel nostro esempio, abbiamo una join interna che restituisce solo i record corrispondenti; cioè, vengono restituiti solo i clienti con coniugi. Donna non ha un coniuge nella tabella, quindi Donna non è inclusa nell'insieme di dati risultante.

Se volete saperne di più sui join, vi consiglio il nostro articolo "Come imparare SQL JOINs"."Sulla nostra piattaforma è disponibile anche un corso interattivo di SQL joins. LearnSQL.it piattaforma.

Esempi di Self Join

Questo è solo un esempio. Quando si inizia a usare SQL quotidianamente, ci si imbatte spesso nella necessità di eseguire self join.

Un caso d'uso comune per la self join è quando esiste una gerarchia tra i record di una tabella. Questo tipo di struttura di dati si chiama struttura ad albero e spesso è necessario unire la tabella con se stessa in SQL. Ecco alcuni esempi.

Esempio 1: Gerarchia dei dipendenti

Ogni dipendente ha un manager, e un manager a sua volta ha il suo manager, tutti nella stessa tabella. Se si desidera aggiungere a ogni record le informazioni relative al manager, è necessario eseguire un self join. Questo esempio è illustrato nell'articolo "Guida illustrata alla Self Join di SQL", per cui si consiglia di dare un'occhiata a questo articolo per vedere come si presenta.

Esempio 2: Gerarchia dei dipartimenti

Ogni dipartimento all'interno di un'organizzazione ha un genitore: ad esempio, il dipartimento Data Science è sotto il dipartimento IT, il dipartimento IT è sotto il Business Support e il Business Support è sotto il consiglio di amministrazione.

Considerate la seguente tabella, departmentche ha questo aspetto:

department_idnameparent_department_id
1Board of directors.
2Operations1
3Control and risk1
4Administration1
5Corporate credit2
6Retail banking2
7Investment2
8Risk management3
9Finance3
10Internal audit3
11IT4
12Legal4
13General services4
14Human resources4

Se si desidera aggiungere il nome del genitore a ciascun reparto, è necessario scrivere un self join:

select c.*,
   p.name as parent_name
from department c 
left join department p 
on c.parent_department_id=p.department_id;

All'interno di questo SELECT, uniamo la tabella department con se stessa per ottenere il nome del reparto genitore come campo aggiuntivo. Si noti che il record il cui department_id è 1 non ha un genitore (parent_department_id è NULL; non è popolato). Questo perché il consiglio di amministrazione si trova in cima alla struttura ad albero. Vogliamo visualizzare questo record nel risultato, quindi usiamo un LEFT JOIN e non un INNER JOIN.

Quando si esegue questo codice, la tabella risultante ha questo aspetto:

department_idnameparent_department_idparent_name
1Board of directors..
2Operations1Board of directors
3Control and risk1Board of directors
4Administration1Board of directors
5Corporate credit2Operations
6Retail banking2Operations
7Investment2Operations
8Risk management3Control and risk
9Finance3Control and risk
10Internal audit3Control and risk
11IT4Administration
12Legal4Administration
13General services4Administration
14Human resources4Administration

Si può facilmente vedere il genitore a cui appartiene ogni reparto: IT è sotto Amministrazione, Amministrazione è sotto Consiglio, ecc.

Esempio 3: Gerarchia delle categorie

Prendiamo ad esempio la pubblicità classificata: quelle popolari pagine web in cui si può affittare, comprare o vendere qualsiasi cosa, da immobili a prodotti e servizi vari. Per inserire un annuncio, si sceglie una categoria e una sottocategoria per l'annuncio. Ad esempio, se si vendono immobili, si può scegliere tra sottocategorie come casa, appartamento o terreno.

Abbiamo una tabella denominata category che contiene informazioni su queste categorie e sottocategorie e sulle loro relazioni. Le relazioni tra le categorie e le sottocategorie di questa tabella sono memorizzate in una struttura genitore-figlio come questa:

category_idcategory_nameparent_category_id
1Real estate.
2Apartments1
3Houses1
4Offices1
5Cars.
6Motorcycles5
7Personal cars5
8Oldtimer5
9Trucks5

Tutte le categorie e le sottocategorie si trovano in questa tabella. Ora, se si vogliono aggiungere informazioni sul genitore a ogni record, è necessario eseguire un self join, ossia unire la tabella a se stessa:

select subcategory.*,
    main.category_name as parent_name
from category subcategory 
left join category main 
on subcategory.parent_category_id = main.category_id;

Ecco il risultato dell'esecuzione di questa istruzione SQL:

category_idcategory_nameparent_category_idparent_name
1Real Estate..
2Apartments1Real Estate
3Houses1Real Estate
4Offices1Real Estate
5Cars..
6Motorcycles5Cars
7Personal cars5Cars
8Oldtimer5Cars
9Trucks5Cars

Relazioni multiple tra due tabelle

Oltre al self join, ci sono situazioni in cui è necessario unire la stessa tabella più di una volta. Una di queste è quando si hanno relazioni multiple tra due tabelle diverse. In questo caso, si unisce la stessa tabella due volte, ma di solito a qualche altra tabella e non necessariamente a se stessa.

Supponiamo che la tabella customer abbia due campi che contengono gli ID delle città. Questo è comune se si hanno due città diverse per ogni cliente, ad esempio la città di residenza (residence_city_id) e la città dell'indirizzo postale dove devono essere inviate le notifiche (notice_city_id):

customer_idfirstnamelastnamebirthdateresidence_city_idnotice_city_id
1JohnMayer1983-05-1216
2MaryMayer1990-07-3016
3LisaRoss1989-04-1567
4AnnaTimothy1988-12-2644
5TimRoss1957-08-1567
6SteveDonell1967-07-0944
7DonnaTrapp1978-06-2322

Abbiamo anche city che contiene l'ID della città (city_id) e il nome della città (name), come visto in precedenza e mostrato di seguito come promemoria:

city_idname
1London
2Manchester
3Liverpool
4Leeds
5Bristol
6Oxford
7Reading
8Brighton
9Sheffield
10York

Ora, se si desidera visualizzare i nomi delle città, è necessario unire la tabella city due volte:

select cust.customer_id,
      cust.firstname,
      cust.lastname,
      cust.birthdate,
      cust.residence_city_id,
      cust.notice_city_id,
      residence_city.name as residence_city_name,
      notice_city.name as notice_city_name
from customer cust 
join city residence_city 
on cust.residence_city_id=residence_city.city_id
join city notice_city 
on cust.notice_city_id=notice_city.city_id;

Vediamo cosa succede in questo codice. Per prima cosa, uniamo customer e city con residence_city_id come chiave. Otteniamo residence_city_name abbinandolo a city_id nella tabella. city nella tabella. Si esegue una seconda unione tra customer e city per ottenere notice_city_name. La chiave utilizzata in questo caso è notice_city_id, che corrisponde anche a city_id nella tabella. city nella tabella.

Utilizziamo gli alias della tabella cust per customer, residence_city per la prima copia di city per ottenere il nome della città di residenza e notice_city per la seconda copia di city per ottenere il nome della città di avviso. Gli alias vengono utilizzati per definire le colonne della tabella risultante. Gli alias vengono utilizzati anche durante la join per definire le colonne chiave. Anche in questo caso, gli alias sono necessari per distinguere le due copie di city.

Quando si esegue questo codice, si ottiene il seguente risultato:

customer_idfirstnamelastnamebirthdateresidence_city_idnotice_city_idresidence_city_namenotice_city_name
1JohnMayer1983‑05‑1216LondonOxford
2MaryMayer1990-07-3016LondonOxford
3LisaRoss1989-04-1567OxfordReading
4AnnaTimothy1988-12-2644LeedsLeeds
5TimRoss1957-08-1567OxfordReading
6SteveDonell1967-07-0944LeedsLeeds
7DonnaTrapp1978-06-2322ManchesterManchester

Ora abbiamo due colonne aggiuntive con i nomi delle città corrispondenti.

In questo caso utilizziamo join semplici (cioè interni), ma è possibile utilizzare qualsiasi tipo di join a seconda delle necessità. Se non conoscete le join di SQL e volete saperne di più sui diversi tipi, vi consiglio di leggere gli articoli "Come imparare le join" e "Come esercitarsi con le join" che trattano questi argomenti. Se preferite imparare guardando i video. Consiglio vivamente l'episodio che tratta le Join.

Unire due volte la stessa tabella

In questo articolo abbiamo discusso quando è necessario unire due volte la stessa tabella in SQL e abbiamo visto alcuni casi d'uso comuni. Abbiamo spiegato come farlo e come si presenta la sintassi SQL. Le auto-unioni con dati gerarchici e le relazioni multiple tra due tabelle sono solo due delle situazioni in cui è necessario unire due volte la stessa tabella. Ce ne sono altre; in genere, si tratta di aggiungere una o più colonne a un set di risultati provenienti dalla stessa tabella nella stessa colonna.

Se volete saperne di più sulle unioni, comprese le autounioni, vi consiglio il nostro corso interattivo sulle unioni SQL disponibile sulla nostra piattaforma. LearnSQL.it piattaforma. Quando si parla di SQL, è importante fare pratica; il nostro corso è pensato proprio per questo!