【问题标题】:Why are the two queries different (left join on ... and ... as opposed to using where clause)为什么这两个查询不同(左连接 ... 和 ... 而不是使用 where 子句)
【发布时间】:2014-06-20 07:34:40
【问题描述】:

我想知道为什么以下两个查询会产生不同的结果(第一个查询的行数比第二个多)。

SELECT * FROM A
  JOIN ...
  JOIN ...
  JOIN C ON ...
  LEFT JOIN B ON B.id = A.id AND B.otherId = C.otherId

相对于:

SELECT * FROM A
  JOIN ...
  JOIN ...
  JOIN C ON ...
  LEFT JOIN B ON B.id = A.id
WHERE B.otherId = C.otherId

请帮助我理解。在第二个查询中,左连接只有一个条件,所以它不应该包括第一个查询的所有结果等等(额外的行有不匹配的otherId)。然后WHERE 子句应确保otherId 匹配,就像在第一个查询中一样。为什么它们不同?

【问题讨论】:

  • WHERE 在执行JOIN 之前首先由查询引擎执行。原因是为什么要加入,如果我们稍后要过滤一些行。查询引擎非常擅长优化您编写的查询。
  • 您使用的Where 子句有效地将您的Outer Join 更改为Inner Join。第一个将包含没有otherId 匹配为Null 的记录,但第二个将在Where 过滤器中丢弃它们。

标签: sql oracle


【解决方案1】:

查询引擎首先执行WHERE,然后再执行JOIN
原因是如果我们稍后要过滤一些行,为什么要使用昂贵的JOIN。 查询引擎非常擅长优化您编写的查询。

此外,您只会在OUTER JOINs 中看到此效果。在内部连接中,WHEREJOIN 条件的行为相同。

【讨论】:

    【解决方案2】:

    第二个查询返回的行数较少,因为您的 where 子句将记录过滤掉,这实质上是将查询从左外连接更改为内连接。因此,您需要小心放置过滤器的位置,但如果您要进行内部连接,这无关紧要。

    【讨论】:

      【解决方案3】:

      您已收到正确答案,但请允许我更深入地研究一下加入条件和过滤条件之间的区别。使用左连接进行简单查询:

      select a.Key, a.NonKey1, b.NonKey2
      from a
      left join b on b.Key = a.Key;
      

      这列出了表a 中的所有NonKey1 值以及表b 中具有匹配键值的任何NonKey2 字段,或者列出了没有匹配项的NULL。一个常见的变体是只查看a 中与b 不匹配的那些行:

      select a.Key, a.NonKey1, b.NonKey2
      from a
      left join b on b.Key = a.Key
      where b.Key is null;
      

      小心!如果您不小心写了where b.Key is not null,您刚刚将外部联接更改为常规内部联接。有时这样做,看看质量检查是否能抓住它。转念一想,不要。 (另外,在选择列表中包含b.NonKey2 是没有意义的,因为它只能是NULL,但我们暂时将其留在那里。)连接基于两个表的键字段匹配。连接完成后,所有连接成功的行都将被丢弃,只保留没有匹配的结果。这意味着连接条件中的b.Key不能NULL,过滤条件中的必须NULL,以便将一行添加到结果集中。好吧,这就是我们想要的。但是考虑一下如果我们将检查移动到连接条件的一部分会发生什么。

      select a.Key, a.NonKey1, b.NonKey2
      from a
      left join b on b.Key = a.Key and b.Key is null;
      

      结果是来自a 的所有内容,而来自b 的任何内容都没有。可能不是我们想要的。如果您考虑一下,您会发现我们也可以写on 0 = 1 并得到相同的结果。我们所做的是将值从NULL 表示一件事(成功)的上下文移动到NULL 表示完全不同的事情(失败)的上下文。

      因此,在计算机语言中和在人类语言中一样,请注意上下文。它可以完全改变你想说的话的意思。

      【讨论】:

        猜你喜欢
        • 2011-02-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-07
        相关资源
        最近更新 更多