所以,我有以下两个问题。在第一个表中,rcv_transaction
表首先由select子句中的TRANSACTION_TYPE过滤,然后连接到其他表,而在第二个查询中,表首先加入,然后在WHERE子句中过滤。结果完全不同。第一个查询产生的结果几乎是第二个查询的两倍。对我来说,他们应该执行相同的任务。我在这里错过了什么?有什么区别?
第一。查询
SELECT pl.*
FROM po_headers_all ph,
po_lines_all pl,
(SELECT *
FROM rcv_transactions r
WHERE r.TRANSACTION_TYPE = 'DELIVER') rt
WHERE ph.PO_HEADER_ID = pl.PO_HEADER_ID
AND rt.po_header_id(+) = pl.po_header_id
AND rt.po_line_id(+) = pl.po_line_id
第二次查询
SELECT pl.*
FROM po_headers_all ph,
po_lines_all pl,
rcv_transactions rt
WHERE ph.PO_HEADER_ID = pl.PO_HEADER_ID
AND rt.po_header_id(+) = pl.po_header_id
AND rt.po_line_id(+) = pl.po_line_id
AND rt.transaction_type = 'DELIVER'
答案 0 :(得分:2)
使用ANSI 92连接语法,您的查询将被重写为:
SELECT pl.*
FROM po_headers_all ph,
INNER JOIN po_lines_all pl,
ON ph.PO_HEADER_ID = pl.PO_HEADER_ID
LEFT JOIN rcv_transactions rt
ON rt.po_header_id = pl.po_header_id
AND rt.po_line_id = pl.po_line_id
AND rt.transaction_type = 'DELIVER';
和
SELECT pl.*
FROM po_headers_all ph,
INNER JOIN po_lines_all pl,
ON ph.PO_HEADER_ID = pl.PO_HEADER_ID
LEFT JOIN rcv_transactions rt
ON rt.po_header_id = pl.po_header_id
AND rt.po_line_id = pl.po_line_id
WHERE rt.transaction_type = 'DELIVER';
由于当此表中没有对应的行时,您对rcv_transactions
的连接是左连接,因此查询将返回NULL。
但是,您在WHERE
条款rt.transaction_type = 'DELIVER'
中规定了第二个查询,因此rcv_transactions
中不存在任何匹配项的行将被排除,因为NULL
不等于DELIVER
。这有效地将您的LEFT JOIN变为INNER JOIN。在第一个查询中,尽管此谓词是JOIN
的一部分,因此您不会影响整体结果,只会影响已连接的记录。
答案 1 :(得分:0)
如果检查执行计划,您将看到第二个查询不执行外部联接,正如GarethD已经解释过的那样。将join运算符添加到最后一行以将其包含为连接条件:
AND rt.transaction_type(+) = 'DELIVER'