- Cos'è un Inner Join?
- Cos'è un'unione esterna?
- Eseguire join esterni utilizzando il simbolo (+)
Come praticamente tutti i database relazionali, Oracle consente di generare query che si combinano o JOIN
righe da due o più tabelle per creare il set di risultati finale. Sebbene esistano numerosi tipi di join eseguibili, i più comuni sono gli INNER JOIN
e il OUTER JOIN
.
In questo tutorial esploreremo brevemente la differenza tra INNER
e OUTER JOIN
e quindi esaminare il metodo abbreviato fornito da Oracle per eseguire OUTER JOINS
in particolare utilizzando il +
simbolo dell'operatore.
Cos'è un Inner Join?
Un INNER JOIN
in un database relazionale è semplicemente l'unione di due o più tabelle in cui il risultato conterrà solo dati che soddisfano tutte le condizioni di join .
Ad esempio, qui abbiamo una library
di base schema con due tabelle:books
e languages
. Le languages
table è solo un elenco di possibili nomi di lingua e un id
di lingua univoco :
SELECT * FROM library.languages;
id name
1 English
2 French
3 German
4 Mandarin
5 Spanish
6 Arabic
7 Japanese
8 Russian
9 Greek
10 Italian
Nel frattempo, i nostri books
la tabella ha un language_id
riga che per la maggior parte, ma non per tutti, i libri contiene semplicemente il language_id
associato alla lingua originale pubblicata del libro:
SELECT * FROM
books
ORDER BY
id
FETCH FIRST 10 ROWS ONLY;
id title author year_published language_id
1 In Search of Lost Time Marcel Proust 1913 2
2 Ulysses James Joyce 1922 1
3 Don Quixote Miguel de Cervantes 1605 5
4 Moby Dick Herman Melville 1851 1
5 Hamlet William Shakespeare 1601 (null)
6 War and Peace Leo Tolstoy 1869 8
7 The Odyssey Homer -700 9
8 The Great Gatsby F. Scott Fitzgerald 1925 1
9 The Divine Comedy Dante Alighieri 1472 10
10 Madame Bovary Gustave Flaubert 1857 2
In molti casi, potremmo voler eseguire un INNER JOIN
dei books
e languages
tabelle così invece di visualizzare l'insensato language_id
valore di ogni libro, possiamo effettivamente vedere il language name
invece.
SELECT
b.id,
b.title,
b.author,
b.year_published,
l.name language
FROM
books b
INNER JOIN
library.languages l
ON
b.language_id = l.id
ORDER BY
b.id
FETCH FIRST 10 ROWS ONLY;
id title author year_published language
1 In Search of Lost Time Marcel Proust 1913 French
2 Ulysses James Joyce 1922 English
3 Don Quixote Miguel de Cervantes 1605 Spanish
4 Moby Dick Herman Melville 1851 English
6 War and Peace Leo Tolstoy 1869 Russian
7 The Odyssey Homer -700 Greek
8 The Great Gatsby F. Scott Fitzgerald 1925 English
9 The Divine Comedy Dante Alighieri 1472 Italian
10 Madame Bovary Gustave Flaubert 1857 French
11 The Brothers Karamazov Fyodor Dostoyevsky 1880 Russian
Ciò che è fondamentale notare qui è che il nostro set di risultati era leggermente diverso nelle due query precedenti. Nel primo, abbiamo semplicemente elencato il primo 10
libri, ma nel INNER JOIN
query stiamo solo restituendo risultati che soddisfano tutte le condizioni da entrambe le tabelle. Per questo motivo, il record di Hamlet
(che ha un language_id
valore di null
o vuoto) viene ignorato e non restituito nel risultato del nostro INNER JOIN
.
Cos'è un'unione esterna?
Invece di restituire esclusivamente risultati che soddisfano tutte le condizioni di unione di un INNER JOIN
, un OUTER JOIN
restituisce non solo risultati che soddisfano tutte le condizioni, ma anche restituisce le righe di una tabella che non soddisfano la condizione. La tabella scelta per questo "bypass" dei requisiti condizionali è determinata dalla direzionalità o "lato" del join, tipicamente indicato come LEFT
o RIGHT
join esterni.
Quando definisci un lato del tuo OUTER JOIN
, stai specificando quale tabella restituirà sempre la sua riga anche se opposta la tabella sull'altro lato del join è mancante o null
valori come parte della condizione di unione.
Pertanto, se eseguiamo lo stesso JOIN
di base come sopra per recuperare books
e language names
, sappiamo che i nostri books
la tabella dovrebbe sempre restituire dati, quindi il nostro JOIN
il lato dovrebbe "puntare verso" i nostri books
tabella, creando così i languages
tabella il OUTER
tabella che vi alleghiamo.
Per fare ciò, cambiamo semplicemente:
books b INNER JOIN library.languages l
…a questo:
books b LEFT OUTER JOIN library.languages l
Pertanto, l'intera query e il set di risultati sembrano quasi identici a INNER JOIN
tranne quella piccola alterazione:
SELECT
b.id,
b.title,
b.author,
b.year_published,
l.name language
FROM
books b
LEFT OUTER JOIN
library.languages l
ON
b.language_id = l.id
ORDER BY
b.id
FETCH FIRST 10 ROWS ONLY;
id title author year_published language
1 In Search of Lost Time Marcel Proust 1913 French
2 Ulysses James Joyce 1922 English
3 Don Quixote Miguel de Cervantes 1605 Spanish
4 Moby Dick Herman Melville 1851 English
5 Hamlet William Shakespeare 1601 (null)
6 War and Peace Leo Tolstoy 1869 Russian
7 The Odyssey Homer -700 Greek
8 The Great Gatsby F. Scott Fitzgerald 1925 English
9 The Divine Comedy Dante Alighieri 1472 Italian
10 Madame Bovary Gustave Flaubert 1857 French
Come previsto, utilizzando un LEFT OUTER JOIN
invece del precedente INNER JOIN
, stiamo ottenendo il meglio da entrambi i mondi:non saltiamo nessun books
record (come Hamlet
) semplicemente perché language_id
il valore è null
per quel record, ma per tutti i record in cui language_id
esiste, otteniamo il language name
ben formattato ottenuto dalle nostre languages
tabella.
Esecuzione di join esterni utilizzando il simbolo (+)
Come indicato nella documentazione ufficiale, Oracle fornisce uno speciale outer join operator
(il +
simbolo) che è un'abbreviazione per eseguire OUTER JOINS
.
In pratica, il +
il simbolo è posto direttamente nel condizionale istruzione e sul lato della tabella opzionale (quella che può contenere valori vuoti o null
valori all'interno del condizionale).
Pertanto, possiamo ancora una volta riscrivere il nostro LEFT OUTER JOIN
sopra istruzione utilizzando il +
operatore in questo modo:
SELECT
b.id,
b.title,
b.author,
b.year_published,
l.name language
FROM
books b,
library.languages l
WHERE
l.id (+)= b.language_id
ORDER BY
b.id
FETCH FIRST 10 ROWS ONLY;
I risultati sono gli stessi del LEFT OUTER JOIN
standard esempio sopra, quindi non li includeremo qui. Tuttavia, c'è un aspetto critico da notare sulla sintassi usando il +
operatore per OUTER JOINS
.
Il +
l'operatore deve essere sul lato sinistro del condizionale (a sinistra di uguale a =
cartello). Pertanto, in questo caso, perché vogliamo assicurarci che il nostro languages
table è la tabella opzionale che può restituire null
valori durante questo confronto, abbiamo scambiato l'ordine delle tabelle in questo condizionale, quindi languages
è a sinistra (ed è opzionale) mentre books
è sulla destra.
Infine, a causa di questo riordino dei lati della tabella nel condizionale quando si utilizza il +
operatore, è importante rendersi conto che quanto sopra è semplicemente un'abbreviazione per un RIGHT OUTER JOIN
. Ciò significa che questo frammento di query:
FROM
books b,
library.languages l
WHERE
l.id (+)= b.language_id
…è effettivamente identico a questo:
FROM
library.languages l
RIGHT OUTER JOIN
books b
ON
b.language_id = l.id