【问题标题】:SQL - Difference between these Joins?SQL - 这些连接之间的区别?
【发布时间】:2010-11-08 20:06:31
【问题描述】:

我现在大概应该知道了,但是如果有的话,下面的两个陈述之间有什么区别?

嵌套连接:

SELECT
    t1.*
FROM
    table1 t1
    INNER JOIN table2 t2
        LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID
    ON t2.table2_ID = t1.table1_ID

更传统的连接:

SELECT
    t1.*
FROM
    table1 t1
    INNER JOIN table2 t2 ON t2.table2_ID = t1.table1_ID
    LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID

【问题讨论】:

  • 执行它们时是否给出相同的结果?
  • 第二个比第一个更容易理解——即使你在第一个中的 LOJ 周围加上(括号)。期待在这个问题上投票给一个好的答案。
  • 在我有限的测试中,是的,它们确实给出了相同的结果。但是,我不想在此基础上做出任何假设,因为我只是用有限的数据进行了快速测试。
  • 哎呀,用“视觉”查询设计器构建的重写视图的闪回。一个查询中的左右连接、嵌套连接以及试图找出和/或没有括号的顺序或操作的恐怖。

标签: sql sql-server database tsql join


【解决方案1】:

嗯,这是操作的顺序..

SELECT
    t1.*
FROM
    table1 t1
    INNER JOIN table2 t2
        LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID
    ON t2.table2_ID = t1.table1_ID

可以改写为:

SELECT
    t1.*
FROM
       table1 t1                                                       -- inner join t1
    INNER JOIN 
       (table2 t2 LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID)  -- with this 
    ON t2.table2_ID = t1.table1_ID                                     -- on this condition

所以基本上,首先你 LEFT JOIN t2 和 t3,基于连接条件:table3_ID = table2_ID,然后你 INNER JOIN t1 和 t2 on table2_ID = table1_ID。

在您的第二个示例中,您首先将 t1 与 t2 进行 INNER JOIN,然后在条件 table2_ID = table1_ID 上将结果与表 t3 进行 LEFT JOIN。

SELECT
    t1.*
FROM
    table1 t1
    INNER JOIN table2 t2 ON t2.table2_ID = t1.table1_ID
    LEFT JOIN table3 t3 ON t3.table3_ID = t2.table2_ID        

可以改写为:

SELECT
    t1.*
FROM
        (table1 t1 INNER JOIN table2 t2 ON t2.table2_ID = t1.table1_ID) -- first inner join
    LEFT JOIN                                                           -- then left join
        table3 t3 ON t3.table3_ID = t2.table2_ID                        -- the result with this

编辑

我很抱歉。我的第一句话是错误的。这两个查询将产生相同的结果,但性能可能会有所不同,因为在某些情况下(当表 1 仅包含表 2 中元素的一个子集时)第一个查询的执行速度可能比第二个查询慢,因为 LEFT JOIN 将首先执行 - 然后才与 table1 相交。与允许查询优化器完成工作的第二个查询相反。

【讨论】:

  • 显然操作顺序不同,但有什么实际区别(性能、结果,什么)?
  • 请举例说明查询会返回不同结果的数据。我无法生成任何东西。
  • 好的,感谢您对这些人的想法。和我当时想的差不多。结果将是相同的,但查询的执行可能会有所不同。我认为为了便于使用,我会将旧的(嵌套)查询更改为使用更传统的语法。
【解决方案2】:

对于您的具体示例,我认为生成的查询计划应该没有任何差异,但在可读性方面肯定存在差异。你的第二个例子更容易理解。

如果您要反转示例中的连接类型,您最终可能会得到截然不同的结果。

SELECT    t1.*
FROM    table1 t1
    LEFT JOIN table2 t2 ON t2.table2_ID = t1.table1_ID
    INNER JOIN table3 t3 ON t3.table3_ID = t2.table2_ID

-- may not produce the same results as...

SELECT    t1.*
FROM    table1 t1
    LEFT JOIN table2 t2
        INNER JOIN table3 t3 ON t3.table3_ID = t2.table2_ID
    ON t2.table2_ID = t1.table1_ID

基于连接顺序在许多情况下确实很重要的事实 - 应该仔细考虑如何编写连接语法。如果您发现第二个示例是您真正想要完成的,我会考虑重写查询,以便您可以更加强调连接的顺序...

SELECT    t1.*
FROM    table2 t2
        INNER JOIN table3 t3 ON t3.table3_ID = t2.table2_ID
        RIGHT JOIN table1 t1 ON t2.table2_ID = t1.table1_ID

【讨论】:

    【解决方案3】:

    查看这两个查询有何不同的最佳方法是比较这两个查询的查询计划。

    这些IF的结果集没有区别,对于table2中的给定行,table3中总是有行。

    我在我的数据库上尝试过,查询计划的不同之处在于 1. 对于第一个查询,优化器选择先对表 2 和表 3 进行连接。 2.对于第二个查询,优化器选择先join table1和table2。

    【讨论】:

    • 对我来说,我的真实查询的执行计划是完全一样的。
    【解决方案4】:

    如果您的 DBMS 优化器达到标准,您应该会发现这两个查询之间没有任何区别。然而,即使对于大型、高成本的平台,这也不是我有信心做出的假设,所以当我发现查询计划(以及因此执行时间)各不相同时,我并不感到惊讶。

    【讨论】:

      猜你喜欢
      • 2012-09-02
      • 1970-01-01
      • 1970-01-01
      • 2013-02-08
      • 1970-01-01
      • 2011-07-14
      • 2011-06-10
      • 2021-02-09
      相关资源
      最近更新 更多