Oracle
 sql >> Base de données >  >> RDS >> Oracle

Oracle - Jointure externe gauche sur plusieurs tables ne renvoyant pas les valeurs nulles souhaitées

Vous devez mieux comprendre le fonctionnement d'un LEFT JOIN (jointures externes en général - jointure gauche/droite et complète [outer])

Le LEFT JOIN s'effectue toujours en deux étapes :

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

Étape 1 - le LEFT JOIN est effectué en premier (en utilisant les conditions spécifiées dans la clause ON pour joindre deux tables)
Étape 2 - les conditions WHERE sont appliquées à un jeu de résultats généré par la jointure à l'étape 1

Comment fonctionne LEFT JOIN - un petit rappel :LEFT JOIN renvoie toujours TOUTES les lignes de la table de gauche, même celles pour lesquelles il n'y a pas de correspondance dans la table de droite. Lorsqu'il n'y a pas de correspondance (la condition ON est évaluée comme fausse), LEFT JOIN renvoie des valeurs NULL pour la table de droite.
Le RIGHT JOIN fonctionne de la même manière, mais il renvoie toutes les lignes de la table de DROITE, pas celle de gauche comme LEFT JOIN.

DONC si vous avez cette requête :

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'

la base de données effectue d'abord le LEFT JOIN, c'est-à-dire :

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 requête ci-dessus donne le résultat suivant (notez les valeurs NULL dans les 3 dernières lignes à droite) :

|   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) |

Ensuite, la base de données exécute la condition WHERE sur le jeu de résultats ci-dessus :

WHERE H.STATUS='COMPLETED'

Depuis NULL='COMPLETED' est évalué à FALSE, alors le résultat final de la requête est :

|     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 |

c'est-à-dire :tous les NULL ont été ignorés.
Voir cette démo :http://sqlfiddle .com/#!9/e2ed0/3

Si vous souhaitez également obtenir des enregistrements avec des valeurs NULL, vous devez modifier cette condition en :

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

vous pouvez également supprimer cette condition de la clause WHERE et l'ajouter à la condition ON du LEFT JOIN, c'est-à-dire :

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' )

voir la dernière requête dans cette démo :http://sqlfiddle.com/#!9/e2ed0 /3