代码之家  ›  专栏  ›  技术社区  ›  TehOne

SQL-这些连接之间的区别?

  •  6
  • TehOne  · 技术社区  · 15 年前

    我现在可能已经知道这一点了,但是,如果下面这两个陈述之间有什么区别呢?

    嵌套联接:

    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
    
    4 回复  |  直到 15 年前
        1
  •  5
  •   Mike Dinescu    15 年前

    嗯,这是操作顺序……

    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
    

    因此,基本上,首先根据连接条件,将t2与t3连接起来:table3_id=table2_id,然后在table2_id=table1_id上将t1与t2内部连接起来。

    在第二个示例中,您首先使用t2将T1内部联接,然后在条件table2_id=table1_id下左联接结果与表t3内部联接。

    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中元素的一个子集时),因为将首先执行左联接,然后才与表1相交。与允许查询优化器执行其任务的第二个查询不同。

        2
  •  4
  •   Scott Ivey    15 年前

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

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

    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
  •  2
  •   Ralph Wiggum    15 年前

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

    这些结果集没有区别 如果 对于表2中给定的行,表3中总是有行。

    我在我的数据库中尝试过,但查询计划的不同之处在于 1。对于第一个查询,优化器选择首先对表2和表3进行联接。 2。对于第二个查询,优化器选择首先联接表1和表2。

        4
  •  0
  •   Mike Woodhouse    15 年前

    如果您的DBMS优化器运行正常,那么您应该看到这两个查询之间完全没有区别。然而,即使是对于大型钢铁、高成本的平台,这也不是我有信心做出的假设,因此我对于发现查询计划(以及因此而产生的执行时间)的变化也相当没有信心。