Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Oracle- Junção externa esquerda em várias tabelas não retornando valores nulos desejados


Você precisa entender melhor como um LEFT JOIN funciona (junções externas em geral - left/right e full [outer] join)

O LEFT JOIN é sempre realizado em duas etapas:
SELECT ....
FROM table1
LEFT JOIN table1 ON join_conditions
WHERE where_conditions

Passo 1 - o LEFT JOIN é executado primeiro (usando as condições especificadas na cláusula ON para unir duas tabelas)
Passo 2 - as condições WHERE são aplicadas a um resultado gerado pelo join no passo 1

Como o LEFT JOIN funciona - um lembrete rápido:LEFT JOIN retorna sempre TODAS as linhas da tabela da esquerda, mesmo essas linhas para as quais não há correspondência na tabela da direita. Quando não há correspondência (a condição ON é avaliada como falsa), LEFT JOIN retorna NULLs para a tabela da direita.
O RIGHT JOIN funciona da mesma maneira, mas retorna todas as linhas da tabela RIGHT, não a da esquerda como LEFT JOIN.

Então, se você tiver esta consulta:
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'

o banco de dados primeiro executa o LEFT JOIN, ou seja:
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

A consulta acima fornece o seguinte resultado (observe NULLs nas últimas 3 linhas do lado direito):
|   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 então o banco de dados executa a condição WHERE no conjunto de resultados acima:
WHERE H.STATUS='COMPLETED'

Desde NULL='COMPLETED' avalia como FALSE, então o resultado final da consulta é:
|     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 |

isto é:todos os NULLs foram ignorados.
Veja esta demonstração:http://sqlfiddle .com/#!9/e2ed0/3

Se você deseja obter também registros com valores NULL, você precisa alterar esta condição para:
WHERE ( H.STATUS='COMPLETED' OR H.STATUS IS NULL )

você também pode remover essa condição da cláusula WHERE e adicioná-la à condição ON do LEFT JOIN, ou seja:
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' )

veja a última consulta nesta demonstração:http://sqlfiddle.com/#!9/e2ed0 /3