我正在使用以下传统的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共有的记录。那么这个查询是否执行了两种数据集的联合?
答案 0 :(得分:1)
LEFT JOIN
到table2
实际上是INNER JOIN
。 WHERE
子句正在撤消外连接。所以我认为这是等效的查询:
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
的所有记录。
您可以将其想象如下:假设table1
和table2
实际上保持连接,这样(中间)结果包含来自table1
的所有元组以及{的属性{1}} table2
与table1.job
匹配,table2.job
的值为table2
- job
不匹配的属性{1}}然后,where
条件table2.column1= table4.key
将删除table2.column1
与table4
中的任何记录都不匹配的(中间)结果中的所有记录。请注意,由左连接产生的null
中的table2.column1
- 值将永远不会匹配,并会将这些记录过滤掉。因此,table1.job
和table2.job
不匹配的结果中不会有任何记录。