【问题标题】:INNER JOIN condition in WHERE clause or ON clause?WHERE 子句或 ON 子句中的 INNER JOIN 条件?
【发布时间】:2014-02-07 09:25:45
【问题描述】:

我今天打错了一个查询,但它仍然有效并给出了预期的结果。我的意思是运行这个查询:

SELECT e.id FROM employees e JOIN users u ON u.email=e.email WHERE u.id='139840'

但我不小心运行了这个查询

SELECT e.id FROM employees e JOIN users u ON u.email=e.email AND u.id='139840'

(请注意最后一个子句中的AND 而不是WHERE

并且两者都从用户 ID 返回了正确的员工 ID。

这两个查询有什么区别?第二种形式是否只加入符合条件的 2 个表的成员,而第一种形式将加入整个表,然后运行查询?一个比另一个效率更高还是更低?我还缺少其他东西吗?

谢谢!

【问题讨论】:

  • 查询优化器可能会将它们视为等价的,因为它们具有相同的含义......
  • 如果您要切换到 LEFT OUTER JOIN,那么只有第二个 woud 会“按预期”工作
  • INNER JOIN ON vs WHERE clause 的可能重复项

标签: mysql sql performance inner-join


【解决方案1】:

我在工作中与我们团队的同事提出了这个问题。这个响应有点以 SQL Server 为中心,而不是 MySQL。但是,优化器在操作上应该与 SQL 和 MySQL 有相似之处..

一些想法: 本质上,如果您必须添加 WHERE,则需要进行额外的表扫描以验证每个条件的相等性(这会随着 AND 或数据集、OR 的数量级上升,在第一个真实条件下做出决定) -如果您在示例中具有一个 id 指针,则它会非常快,相反,如果您必须找到属于公司或部门的所有记录,它会变得更加模糊,因为您可能有多个记录。如果可以应用 equals 条件,则在使用具有数以百万计的行的 AuditLog 或 EventLog 表时会更有效。在小型表(大约 200,000 行左右)上,人们不会真正看到这样做的巨大好处。

发件人:亚历山德罗·阿尔皮 http://suxstellino.wordpress.com/2013/01/07/sql-server-logical-query-processing-summary/

来自:Itzik Ben-Gan http://tsql.solidq.com/books/insidetsql2008/Logical%20Query%20Processing%20Poster.pdf

【讨论】:

    【解决方案2】:

    优化器会对它们一视同仁。你可以做一个 EXPLAIN 来证明给自己看。

    因此,写一个更清楚的。

    SELECT e.id
    FROM employees e JOIN users u ON u.email=e.email
    WHERE u.id='139840'
    

    【讨论】:

      【解决方案3】:

      对于像这样的内部连接,它们在逻辑上是等价的。但是,您可能会遇到 join 子句中的条件与 where 子句中的条件不同的情况。

      作为一个简单的说明,假设您像这样进行左连接;

      select x.id
      from x
             left join y
               on x.id = y.id
      ;
      

      这里我们从 x 中取出所有行,不管 y 中是否有匹配的 id。现在假设我们的连接条件增长了——我们不仅根据 id 查找 y 中的匹配项,还根据 id_type 查找匹配项。

      select x.id
      from x
             left join y
               on x.id = y.id
               and y.id_type = 'some type'
      ;
      

      同样,这给出了 x 中的所有行,而不管 y 中是否存在匹配的 (id, id_type)。

      这是非常不同的,但是:

      select x.id
      from x
             left join y
               on x.id = y.id
      where y.id_type = 'some type'
      ;
      

      在这种情况下,我们会选择 x 的所有行并尝试匹配 y 中的行。现在对于 y 中没有匹配的行,y.id_type 将为空。正因为如此,y.id_type = 'some type' 不满足,所以那些没有匹配的行被丢弃,这实际上变成了一个内连接。

      长话短说:对于内部连接,条件去向无关紧要,但对于外部连接,它可以。

      【讨论】:

        【解决方案4】:

        如果它是外部联接而不是内部联接,您会得到意想不到的结果,但是在使用内部联接时,是否使用附加联接条件而不是 WHERE 子句并没有真正的区别。

        就性能而言,它们很可能是相同的,但不能确定。

        【讨论】:

          【解决方案5】:

          在 INNER JOIN 的情况下,两个查询在语义上是相同的,这意味着它们保证具有相同的结果。如果您使用的是 OUTER 连接,则两个查询的含义可能会大不相同,结果也不同。

          就性能而言,我预计这两个查询会产生相同的执行计划。但是,查询引擎可能会让您大吃一惊。唯一知道的方法是查看这两个查询的执行计划。

          【讨论】:

            猜你喜欢
            • 2010-11-04
            • 1970-01-01
            • 2013-08-11
            • 2014-10-06
            • 2011-06-12
            • 2012-04-25
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多