混合SQL内部和外部联接

时间:2017-05-31 18:10:39

标签: sql oracle join left-join

我正在使用以下传统的Oracle SQL查询:

SELECT *
FROM
table1, table2, table3, table4
WHERE 
    table1.job= table2.job(+)
AND table1.event = table3.event(+)
AND
    ((table2.column1= table4.key AND table4.resource_type = 'xxx')
    OR (table2.column2 = table4.key AND table4.resource_type = 'yyy'))

我看到该表在table2上有一个左外连接,而table1在table3上有一个左外连接。但是现在最后一个条款做了什么?

当我查看维恩图时,我认为它会返回table1的所有内容以及table2和table4共有的记录。那么这个查询是否执行了两种数据集的联合?

3 个答案:

答案 0 :(得分:1)

LEFT JOINtable2实际上是INNER JOINWHERE子句正在撤消外连接。所以我认为这是等效的查询:

SELECT *
FROM table1 JOIN
     table2
     ON table1.job = table2.job JOIN
     table4
     ON (table2.column1 = table4.key AND table4.resource_type = 'xxx') OR
        (table2.column2 = table4.key AND table4.resource_type = 'yyy') LEFT JOIN
     table3
     ON table1.event = table3.event;

Just to be clear关于将外部联接转换为内部联接的观点:

  

如果WHERE子句包含比较列的条件   表B带有常量,那么(+)运算符必须应用于   列,以便Oracle返回表A中的行   为此列生成空值。否则Oracle只返回   简单连接的结果。

答案 1 :(得分:0)

表4记录了(至少)两种资源类型{'xxx','yyy'}。表2列出了第1列中资源类型“xxx”和第2列中资源类型“yyy”的相应ID。

答案 2 :(得分:0)

最后一个子句,即((table2.column1= table4.key AND table4.resource_type = 'xxx') OR (table2.column2 = table4.key AND table4.resource_type = 'yyy'))实际上将table2上的“左连接”变为连接,更具体地说是table1 join table2 join table4之类的连接,这样查询将必须包含table1的所有记录。

您可以将其想象如下:假设table1table2实际上保持连接,这样(中间)结果包含来自table1的所有元组以及{的属性{1}} table2table1.job匹配,table2.job的值为table2 - job不匹配的属性{1}}然后,where条件table2.column1= table4.key将删除table2.column1table4中的任何记录都不匹配的(中间)结果中的所有记录。请注意,由左连接产生的null中的table2.column1 - 值将永远不会匹配,并会将这些记录过滤掉。因此,table1.jobtable2.job不匹配的结果中不会有任何记录。