Oracle-多个表上的左外部联接未返回所需的空值 [英] Oracle- Left outer join on multiple tables not returning desired null values

查看:364
本文介绍了Oracle-多个表上的左外部联接未返回所需的空值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有3张桌子,CAL,SOURCE,HISTORY.

I have 3 tables, CAL,SOURCE,HISTORY.

CAL TABLE CAL_DATE 01/05/16 02/05/16 03/05/16 04/05/16 05/05/16 06/05/16 07/05/16

CAL TABLE CAL_DATE 01/05/16 02/05/16 03/05/16 04/05/16 05/05/16 06/05/16 07/05/16

SOURCE TABLE TABLE_ID GROUP 1210 Sales 1211 Reference 1230 Marketing 1245 Sales 1650 Reference 1784 Sales

SOURCE TABLE TABLE_ID GROUP 1210 Sales 1211 Reference 1230 Marketing 1245 Sales 1650 Reference 1784 Sales

HISTORY
RUN_DATE TABLE_ID STATUS 01/05/16 1210 COMPLETED 02/05/16 1210 COMPLETED 02/05/16 1211 COMPLETED 03/05/16 1211 COMPLETED 01/05/16 1230 COMPLETED 03/05/16 1230 COMPLETED

HISTORY
RUN_DATE TABLE_ID STATUS 01/05/16 1210 COMPLETED 02/05/16 1210 COMPLETED 02/05/16 1211 COMPLETED 03/05/16 1211 COMPLETED 01/05/16 1230 COMPLETED 03/05/16 1230 COMPLETED

我使用的查询.

SELECT TO_CHAR(C.CAL_DATE,'mm/dd/yyyy') AS CAL_DATE,TO_CHAR(C.CAL_DATE,'day') AS WDAY,X.* FROM CAL C LEFT OUTER JOIN
(
    SELECT S.GROUP,S.TABLE_ID,H.RUN_DATE,H.STATUS FROM TABLE S 
    LEFT JOIN HISTORY H
    ON S.TABLE_ID=H.TABLE_ID
    WHERE 1=1 
    AND STATUS='COMPLETED'    
)  X
ON TO_CHAR(C.CAL_DATE,'dd/mm/yyyy')=TO_CHAR(RUN_DATE,'dd/mm/yyyy')
AND X.TABLE_ID IN (1210,1211,1230)
WHERE TO_CHAR(C.CAL_DATE,'mm/dd/yyyy') <= TO_CHAR('03/05/2016','mm/dd/yyyy')
ORDER BY SOURCE_TABLE_ID ASC 

下面给出了预期的输出,但是我得到了不同的输出.当我传递多个表ID时,inodation空值会被滤除.请帮助我更正查询.

Expected output is given below but i am getting different output. When I pass more than 1 table id incodition nulls are filtered out. Please help me to correct the query.

CAL_DATE TABLEID Status 01/05/16 1210 Completed 02/05/16 1210 Completed 03/05/16 null null 01/05/16 null null 02/05/16 1211 Completed 03/05/16 1211 Completed 01/05/16 1230 Completed 02/05/16 null null 03/05/16 1230 Completed

CAL_DATE TABLEID Status 01/05/16 1210 Completed 02/05/16 1210 Completed 03/05/16 null null 01/05/16 null null 02/05/16 1211 Completed 03/05/16 1211 Completed 01/05/16 1230 Completed 02/05/16 null null 03/05/16 1230 Completed

推荐答案

您需要更好地了解LEFT JOIN的工作原理(通常是外部联接-左/右和完整[外部]联接)

左联接总是分两个步骤执行:

You need to gain a better understanding how a LEFT JOIN works (outer joins in general - left/right and full [outer] join)

The LEFT JOIN is always performed in two steps:

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

步骤1-首先执行LEFT JOIN(使用ON子句中指定的条件来连接两个表)
步骤2-将WHERE条件应用于步骤1中的联接所生成的结果集

LEFT JOIN的工作方式-快速提醒:LEFT JOIN总是返回左表中的所有行,即使这些表在右表中不匹配.如果没有匹配项(ON条件的结果为false),则LEFT JOIN将为右表返回NULL.
RIGHT JOIN以相同的方式工作,但是它返回RIGHT表中的所有行,而不是左行作为LEFT JOIN.

Step 1 - the LEFT JOIN is performed first (using conditions specified in ON clause to join two tables)
Step 2 - the WHERE conditions is applied to a resulset generated by the join in step 1

How the LEFT JOIN works - a quick reminder: LEFT JOIN returns always ALL rows from the left table, even these rows for which there is no match in the right table. When there is no match (the ON condition evaluates to false), LEFT JOIN returns NULLs for the right table.
The RIGHT JOIN works in the same way, but it returns all rows from the RIGHT table, not the left one as LEFT JOIN.

因此,如果您有以下查询:

SO if you have this query:

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'

数据库首先执行LEFT JOIN,即:

the database first performs the LEFT JOIN, that is:

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

上面的查询给出以下结果(注意在最右端的最后3行中为NULL):

The above query gives the following result (notice NULLs in the last 3 rows on the rigth side):

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

然后数据库对以上结果集执行WHERE条件:

And then the database performs the WHERE condition on the above resultset:

WHERE H.STATUS='COMPLETED'

由于NULL='COMPLETED'的计算结果为FALSE,因此查询的最终结果为:

Since NULL='COMPLETED' evaluates to FALSE, then the final result of the query is:

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

即:所有NULL都被跳过.
观看此演示: http://sqlfiddle.com/#!9/e2ed0/3

that is: all NULLs were skipped.
See this demo: http://sqlfiddle.com/#!9/e2ed0/3

如果您还想获取具有NULL值的记录,则需要将此条件更改为:

If you want to get also records with NULL values, you need to change this condition to:

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

您还可以从WHERE子句中删除该条件,并将其添加到LEFT JOIN的ON条件,即:

you can also remove ths condition from the WHERE clause, and add it to the ON condition of the LEFT JOIN, that is:

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

请参阅此演示中的最后一个查询: http://sqlfiddle.com/#!9/e2ed0/3

see the last query in this demo: http://sqlfiddle.com/#!9/e2ed0/3

这篇关于Oracle-多个表上的左外部联接未返回所需的空值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆