Nelle applicazioni reali solitamente ci si trova ad operare su grandi moli di dati distribuiti su più tabelle. In questi contesti risulta molto utile la clausola JOIN del linguaggio SQL che serve a combinare i dati di due o più tabelle basandosi su alcune condizioni logiche.
In particolare in SQL Server esistono tre differenti tipi di JOIN:
- INNER JOIN
- OUTER JOIN
- CROSS JOIN
Per comprendere le differenze tra le diverse tipologie di JOIN supponiamo di operare su un database dove abbiamo definito due tabelle denominate "Dipendenti" e "Aree" così strutturato:
CREATE TABLE [dbo].[Dipendenti](
[IdDipendente] [int] IDENTITY(1,1) NOT NULL,
[Cognome] [nvarchar](150) NOT NULL,
[Nome] [nvarchar](150) NULL,
[Email] [nvarchar](150) NULL,
[IdArea] [int] NULL,
PRIMARY KEY CLUSTERED
(
[IdDipendente] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[Aree](
[IdArea] [int] IDENTITY(1,1) NOT NULL,
[NomeArea] [nvarchar](255) NOT NULL,
PRIMARY KEY CLUSTERED
(
[IdArea] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Il legame tra le due tabelle è costituito dal campo "IdArea" che indica l’area aziendale a cui ogni dipendente appartiene (ma non necessariamente tutti i dipendenti sono associati ad un’area aziendale come vedremo).
Dopo aver creato queste tabelle popoliamole con alcuni dati:
A questo punto abbiamo tutti gli elementi per analizzare i diversi tipi di JOIN.
INNER JOIN in SQL Server
Questo tipo di JOIN restituisce tutte le righe delle tabelle coinvolte in cui esista una corrispondenza tra i valori delle colonne presenti nella clausola ON. Nel nostro caso potremmo utilizzare questo tipo di JOIN se vogliamo ottenere id, nome, cognome e area di tutti i dipendenti assegnati ad un’area aziendale:
SELECT D.IdDipendente,D.Nome,D.Cognome,A.NomeArea
FROM dbo.Dipendenti D
INNER JOIN dbo.Aree A
ON A.IdArea = D.IdArea
Questa query restituisce il seguente result set:
Con l’INNER JOIN vengono escluse quelle righe della tabella Dipendenti che non hanno una corrispondenza con la tabella Aree in base al campo specificato nella clausola ON del JOIN (quindi IdArea) e cioè le righe evidenziate nella seguente immagine:
In questo caso vengono esclusi i dipendenti con IdDipendente 5 e 6 perché essi non sono assegnati ad alcuna area.
OUTER JOIN in SQL Server
A sua volta l’OUTER JOIN in SQL Server può essere di tre tipi:
- LEFT OUTER JOIN
- RIGHT OUTER JOIN
- FULL OUTER JOIN
Questo tipo di JOIN quando si desidera selezionare tutte le righe della tabella che si trova a sinistra (LEFT) o a destra (RIGHT) della clausola di JOIN o quando si desidera selezionare tutte le righe di entrambe (FULL), indipendentemente dalla corrispondenza tra i campi presenti nella clausola ON.
Nel nostro caso potremmo utilizzare questo tipo di JOIN se vogliamo ottenere id, nome, cognome e area di tutti i dipendenti indipendentemente dal fatto che essi siano assegnati effettivamente ad un’area. Per fare ciò basta sostituire nella query che abbiamo visto in precedenza alla clausola INNER JOIN la clausola LEFT OUTER JOIN
SELECT D.IdDipendente,D.Nome,D.Cognome,A.NomeArea
FROM dbo.Dipendenti D
LEFT OUTER JOIN dbo.Aree A
ON A.IdArea = D.IdArea
In questo caso il risultato è il seguente:
Vengono restituiti tutti i record della tabella a sinistra del JOIN (cioè Dipendenti) anche se non tutti i record hanno un valore nel campo IdArea. Quindi in pratica se c’è una corrispondenza tra le due tabelle viene riportata la relativa area, se non c’è vengono comunque riportati i dati dei dipendenti.
Supponiamo adesso di voler visualizzare il nome di tutte le aree aziendali indipendentemente dal fatto che ad esse appartengano dipendenti. Potremmo allora scrivere:
SELECT A.NomeArea,D.IdDipendente,D.Nome,D.Cognome
FROM dbo.Dipendenti D
RIGHT OUTER JOIN dbo.Aree A
ON A.IdArea = D.IdArea
Il risultato della query sarà allora il seguente:
Vengono restituiti tutti i record della tabella a destra del JOIN (cioè Aree) anche se non tutti i record hanno una corrispondenza con la tabella a sinistra (cioè Dipendenti). Quindi in pratica se c’è una corrispondenza tra le due tabelle viene riportato il relativo dipendente (o dipendenti, infatti alcune righe vengono duplicate), se non c’è vengono comunque riportati i dati delle aree.
Se invece vogliamo ottenere tutti i dati di entrambe le tabelle indipendentemente dall’esistenza di una corrispondenza tra le stesse possiamo utilizzare il FULL OUTER JOIN:
SELECT D.IdDipendente,D.Nome,D.Cognome,A.NomeArea
FROM dbo.Dipendenti D
FULL OUTER JOIN dbo.Aree A
ON A.IdArea = D.IdArea
Il risultato di questa query è il seguente:
Quindi vengono restituiti tutti i record di entrambe le tabelle. Se esiste una corrispondenza dipendente-area tutti i campi della relativa riga contengono valori, altrimenti i campi vengono presentati con valori NULL.
CROSS JOIN in SQL Server
Questo tipo di join combina tutte le righe della tabella a sinistra con tutte le righe della tabella a destra e serve quando si desidera selezionare tutte le possibili combinazioni di righe e colonne da entrambe le tabelle. Quindi se nelle nostra tabelle abbiamo rispettivamente 6 e 4 righe il risultato di questo tipo di JOIN darà 24 righe (6×4):
SELECT D.IdDipendente,D.Nome,D.Cognome,A.NomeArea
FROM dbo.Dipendenti D
CROSS JOIN dbo.Aree A
Da notare che in questo tipo di JOIN la clausola ON ovviamente non va specificata. Esso richiede molto tempo per l’esecuzione rispetto agli altri JOIN e restituisce risultati la cui utilità è molto limitata se non per specifici scopi.
Conclusioni
Concludendo quindi possiamo dire che i JOIN vengono utilizzati per estrapolare dati da più tabelle in un’unica query. Chiaramente nei nostri esempi abbiamo utilizzato un solo JOIN ma in una stessa query possono essere combinate più tabelle con diversi tipi di JOIN. Inoltre per migliorare le prestazioni dei JOIN è opportuno limitare il numero di righe coinvolte in queste operazioni mediante la specifica di una clausola WHERE nella query. E’ bene ricordare, infine, che le prestazioni dei JOIN sono migliori quando le colonne utilizzate per collegare le tabelle sono indicizzate.