【问题标题】:Left outer joins with join condition具有连接条件的左外连接
【发布时间】:2011-12-10 04:09:10
【问题描述】:

有时,以下陈述令人困惑,至少对我来说是这样,尽管我已经使用连接很长时间了。

这里令人困惑的部分是,考虑到第二个左连接

SELECT * FROM table1  
    LEFT JOIN table2 ON table1.id=table2.id  
    LEFT JOIN table3 ON table2.id=table3.id;
  1. 将被视为左表 - 表 1 或表 2(表 2 参与连接条件)。

  2. 如果我没记错的话,左连接结果包括连接条件的匹配结果和左表的不匹配结果。如果左表是表 1(从第 1 点开始),表 1 中的不匹配行将是什么,因为它不参与连接条件。

【问题讨论】:

  • 1.从左到右阅读它的“左连接”是指第一个表。 2. 什么意思不参与join条件?
  • table1 不直接参与第二个连接条件,table2.id=table3.id .. 对吗??
  • @Sukhhhh Table1和Table2左连接的结果就是第二个条件下连接的结果。所以是的,Table1 直接参与了第二次连接。您将无法连接 Table3 中没有与 Table1 AND Table2 匹配的 ID 值的任何数据。请在示例代码之后查看我的答案的更新。
  • 明白了..现在很清楚了..谢谢

标签: sql join


【解决方案1】:
  1. table1table2 连接的结果是第二次连接的左表。
  2. 如果您在table1 中有id 1,而在table2 中没有id 1,但table3 包含id 1,那么id 1 的行将如下所示:

table1.id  table2.id  table3.id
1          NULL       NULL

连接是按照声明的顺序计算的。这意味着您将table3 加入到table1table2 的结果中。

【讨论】:

    【解决方案2】:

    查询将返回Table1 中的所有行。仅当id 值在Table1Table2 之间相等时,它将加入来自Table2 的行。它还将连接来自Table3 的行,其中id 值在(Table1 AND Table2) 和Table3 的连接结果之间相等。因此,如果Table1Table2 之间的第一个连接产生了一个NULL 结果(Table2 中没有等效的id 值),那么第二个连接也将产生一个NULL 结果。例如(使用 SQL Server):

    DECLARE @Table1 TABLE([ID] INT, [Value] VARCHAR(20))
    INSERT INTO @Table1 VALUES(1, 'Table 1 ID 1')
    INSERT INTO @Table1 VALUES(2, 'Table 1 ID 2')
    INSERT INTO @Table1 VALUES(3, 'Table 1 ID 3')
    
    DECLARE @Table2 TABLE([ID] INT, [Value] VARCHAR(20))
    INSERT INTO @Table2 VALUES(1, 'Table 2 ID 1')
    INSERT INTO @Table2 VALUES(3, 'Table 2 ID 3')
    INSERT INTO @Table2 VALUES(5, 'Table 2 ID 5')
    
    DECLARE @Table3 TABLE([ID] INT, [Value] VARCHAR(20))
    INSERT INTO @Table3 VALUES(2, 'Table 3 ID 2')
    INSERT INTO @Table3 VALUES(3, 'Table 3 ID 3')
    INSERT INTO @Table3 VALUES(5, 'Table 3 ID 5')
    
    SELECT * 
    FROM @Table1 T1
    LEFT JOIN @Table2 T2 ON T1.ID = T2.ID
    LEFT JOIN @Table3 T3 ON T2.ID = T3.ID
    

    此查询将产生以下结果:

    ID  Value          ID   Value           ID    Value
    -----------------------------------------------------------
    1   Table 1 ID 1   1    Table 2 ID 1    NULL  NULL
    2   Table 1 ID 2   NULL NULL            NULL  NULL
    3   Table 1 ID 3   3    Table 2 ID 3    3     Table 3 ID 3
    

    为了回答您的问题,Table1 参与第二次联接,因为第二次联接将仅包含来自 Table2 且能够与 Table1 联接的行。换句话说,第二个联接不是Table2Table3,而是Table1Table2Table3 的左联接的结果。因此,在我的示例中,即使 Table2Table3 都有 ID 为 5 的记录,这些记录也不包含在结果集中,因为 Table1 没有 ID 为 5 的记录.

    【讨论】:

    • 现在更清楚了.. 感谢 rsbarro 分享大量信息 :-)
    • 我认为将排序归于连接是不正确的。在您的示例中,如果先连接 table2 和 table3,然后将该结果与 table1 连接,则结果将相同。为了说明,考虑案例 t1 left outer join t2 on t1.a = t2.a join t3 on t1.a = t3.a 。 (第二个连接不是外部连接)当然在这里,dbms 可能会决定先执行 t1xt3 连接,这可能会带来很大的性能优势,因为它可能会消除许多行。我的观点是,您通常不能假设连接的处理顺序。
    • @ElroyFlynn 我明白你在说什么。我并没有从 dbms 如何内部执行查询的角度来解决这个问题,我只是想回答哪些行将在结果集中结束的问题。无论 dbms 如何执行,您仍然不会得到 table3 中不在 table1 和 table2 中的任何记录。
    猜你喜欢
    • 2018-01-16
    • 2010-11-10
    • 2012-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-12
    • 1970-01-01
    • 2020-06-26
    相关资源
    最近更新 更多