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

Oracle:join esterno sinistro su più tabelle che non restituisce i valori null desiderati

Devi capire meglio come funziona un LEFT JOIN (join esterni in generale - left/right e full [outer] join)

Il LEFT JOIN viene sempre eseguito in due passaggi:

SELECT ....
FROM table1
LEFT JOIN table1 ON join_conditions
WHERE where_conditions

Passaggio 1:viene eseguito per primo il LEFT JOIN (utilizzando le condizioni specificate nella clausola ON per unire due tabelle)
Fase 2:vengono applicate le condizioni WHERE a un risultato generato dal join nel passaggio 1

Come funziona LEFT JOIN - un rapido promemoria:LEFT JOIN restituisce sempre TUTTE le righe della tabella di sinistra, anche quelle righe per le quali non c'è corrispondenza nella tabella di destra. Quando non c'è corrispondenza (la condizione ON restituisce false), LEFT JOIN restituisce NULL per la tabella di destra.
Il RIGHT JOIN funziona allo stesso modo, ma restituisce tutte le righe della tabella RIGHT, non quella di sinistra come UNISCITI A SINISTRA.

SO se hai questa domanda:

SELECT S.GROUP,S.TABLE_ID,H.RUN_DATE,H.STATUS 
FROM source_table S 
LEFT JOIN HISTORY H
ON S.TABLE_ID=H.TABLE_ID
WHERE H.STATUS='COMPLETED'

il database esegue prima il LEFT JOIN, ovvero:

SELECT S.GROUP,S.TABLE_ID,H.RUN_DATE,H.STATUS 
FROM source_table S 
LEFT JOIN HISTORY H
ON S.TABLE_ID=H.TABLE_ID

La query precedente fornisce il seguente risultato (notare i NULL nelle ultime 3 righe sul lato destro):

|   S.GROUP | S.TABLE_ID |                 H.RUN_DATE |  H.STATUS |
|-----------|------------|----------------------------|-----------|
|     Sales |       1210 |  January, 05 2016 00:00:00 | COMPLETED |
|     Sales |       1210 | February, 05 2016 00:00:00 | COMPLETED |
| Reference |       1211 | February, 05 2016 00:00:00 | COMPLETED |
| Reference |       1211 |    March, 05 2016 00:00:00 | COMPLETED |
| Marketing |       1230 |  January, 05 2016 00:00:00 | COMPLETED |
| Marketing |       1230 |    March, 05 2016 00:00:00 | COMPLETED |
|     Sales |       1245 |                     (null) |    (null) |
| Reference |       1650 |                     (null) |    (null) |
|     Sales |       1784 |                     (null) |    (null) |

E quindi il database esegue la condizione WHERE sul set di risultati sopra:

WHERE H.STATUS='COMPLETED'

Poiché NULL='COMPLETED' restituisce FALSE, quindi il risultato finale della query è:

|     GROUP | TABLE_ID |                   RUN_DATE |    STATUS |
|-----------|----------|----------------------------|-----------|
|     Sales |     1210 |  January, 05 2016 00:00:00 | COMPLETED |
|     Sales |     1210 | February, 05 2016 00:00:00 | COMPLETED |
| Reference |     1211 | February, 05 2016 00:00:00 | COMPLETED |
| Reference |     1211 |    March, 05 2016 00:00:00 | COMPLETED |
| Marketing |     1230 |  January, 05 2016 00:00:00 | COMPLETED |
| Marketing |     1230 |    March, 05 2016 00:00:00 | COMPLETED |

ovvero:tutti i NULL sono stati ignorati.
Guarda questa demo:http://sqlfiddle .com/#!9/e2ed0/3

Se vuoi ottenere anche record con valori NULL, devi modificare questa condizione in:

WHERE ( H.STATUS='COMPLETED' OR H.STATUS IS NULL )

puoi anche rimuovere questa condizione dalla clausola WHERE e aggiungerla alla condizione ON di LEFT JOIN, ovvero:

SELECT S.GROUP,S.TABLE_ID,H.RUN_DATE,H.STATUS 
FROM source_table S 
LEFT JOIN HISTORY H
ON ( S.TABLE_ID=H.TABLE_ID AND H.STATUS='COMPLETED' )

guarda l'ultima query in questa demo:http://sqlfiddle.com/#!9/e2ed0 /3