Oracle
 sql >> Database >  >> RDS >> Oracle

Join sinistro e destro utilizzando il segno più (+) in Oracle

  • 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