Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 使用SELECT子句中的子查询筛选表与使用where子句筛选表_Sql_Oracle_Join_Subquery - Fatal编程技术网

Sql 使用SELECT子句中的子查询筛选表与使用where子句筛选表

Sql 使用SELECT子句中的子查询筛选表与使用where子句筛选表,sql,oracle,join,subquery,Sql,Oracle,Join,Subquery,因此,我有以下两个问题。在第一个查询中,rcv\u transaction表首先在select子句中按事务类型过滤,然后连接到其他表,而在第二个查询中,表首先连接,然后在WHERE子句中过滤。结果完全不同。第一个查询产生的结果几乎是第二个查询的两倍。对我来说,他们应该完成同样的任务。我错过了什么?有什么区别 第一。质疑 SELECT pl.* FROM po_headers_all ph, po_lines_all pl, (SELECT *

因此,我有以下两个问题。在第一个查询中,
rcv\u transaction
表首先在select子句中按事务类型过滤,然后连接到其他表,而在第二个查询中,表首先连接,然后在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'

使用ANSI 92 join语法,您的查询将重写为:

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

由于当此表中没有相应行时,对
rcv\u事务的联接是左联接,因此查询将返回NULL。

但是,您在
WHERE
子句中规定了
rt.transaction\u type='DELIVER'
,因此,将排除
rcv\u事务中不匹配的任何行,因为
NULL
不等于
DELIVER
。这将有效地将左连接转换为内部连接。在第一个查询中,尽管该谓词是
联接的一部分,但是您不会影响整体结果,只影响联接的记录。

如果检查执行计划,您将看到第二个查询不会执行外部联接,正如GarethD已经解释的那样。将联接运算符添加到最后一行,以将其作为联接条件包括在内:

AND rt.transaction_type(+) = 'DELIVER'

不相关,但是:您应该习惯于where子句中的显式连接而不是隐式连接。Oracle也不鼓励使用专有的
(+)
运算符。对于带有\u no\u名称的@a_horse\u,我发现显式联接更具可读性!而保持可读性意味着在长期支持和开发中实际降低成本……是的,我知道。只是我工作的公司的所有遗留代码都是用这种风格编写的。我无权更改他们的编码方式:)谢谢你的建议,谢谢你的明确回答。因此,据我所知,这些查询不同的唯一原因是因为涉及到外部联接。如果我将所有外部联接更改为内部联接,会发生什么情况?它们还会产生不同的结果吗?不会,它们会产生相同的结果。
AND rt.transaction_type(+) = 'DELIVER'