代码之家  ›  专栏  ›  技术社区  ›  Martin AJ

理解带不同ON子句的自连接[重复]

  •  0
  • Martin AJ  · 技术社区  · 7 年前

    以下是我的表格结构:

    // mytable
    +----+---------+----------+
    | id | related | subject  |
    +----+---------+----------+
    | 1  | NULL    | subject1 |
    | 2  | 1       |          |
    +----+---------+----------+
    

    有两个问题 完全相同的 对我来说,但是 不同的 测试结果:

    SELECT a.id, IFNULL(b.subject, a.subject)
    FROM mytable a
    LEFT JOIN mytable b ON a.id = b.related
    
        +----+----------+
        | 1  | subject1 |
        | 2  |          |
        +----+----------+
    
    SELECT a.id, IFNULL(b.subject, a.subject)
    FROM mytable a
    LEFT JOIN mytable b ON b.id = a.related
    
        +----+----------+
        | 1  | subject1 |
        | 2  | subject1 |
        +----+----------+
    

    看,是的 自己 -加入。那么为什么 ON a.id = b.related ON b.id = a.related 有什么不同?

    2 回复  |  直到 7 年前
        1
  •  3
  •   JNevill    7 年前

    使用运行查询 SELECT * 揭开一些谜团:

    您的第一个查询:

    SELECT *
    FROM mytable a
    LEFT JOIN mytable b ON a.id = b.related;
    

    生成以下内容:

    +----+---------+----------+--------+----------+----------+
    | id | related | subject  |  id1   | related1 | subject1 |
    +----+---------+----------+--------+----------+----------+
    |  2 | 1       | <null>   | <null> | <null>   | <null>   |
    |  1 | <null>  | subject1 | 2      | 1        | <null>   |
    +----+---------+----------+--------+----------+----------+
    

    您的第二个查询:

    SELECT *
    FROM mytable a
    LEFT JOIN mytable b ON b.id = a.related;
    

    产生以下结果:

    +----+---------+----------+--------+----------+----------+
    | id | related | subject  |  id1   | related1 | subject1 |
    +----+---------+----------+--------+----------+----------+
    |  2 | 1       | <null>   | 1      | <null>   | subject1 |
    |  1 | <null>  | subject1 | <null> | <null>   | <null>   |
    +----+---------+----------+--------+----------+----------+
    

    您的第一个查询是加入id 2 至相关 2. .没有相关 2. 自id起 2. 没有主题,你得不到 subject 从你的 ifnull()

    您的第二个查询是加入相关 1 收件人id 1. 对于a.id 2. .这需要 主题 来自b.id 1. 然后你得到一个身份证的主题 2. 因此

    你真的必须在脑海中想出 LEFT JOIN 在这里工作以及它是如何受到 ON 条款因此,这里有两个非常不同的查询。

        2
  •  1
  •   spencer7593    7 年前

    两个查询都从中获取所有行 a

    两个查询都在执行 外面的 加入到 b

    不同的是用于从b中查找“匹配”的条件。

    (这些查询可能看起来是相同的,但事实是它们有显著的不同。)

    作为演示,运行如下查询:

    SELECT a.id             AS `a_id`
         , a.related        AS `a_related`
         , a.subject        AS `a_subject`
         , b.id             AS `b_id`
         , b.related        AS `b_related`
         , b.subject        AS `b_subject`
      FROM mytable a
      LEFT
      JOIN mytable b
        ON b.related = a.id
    

    然后更改 ON 条款

        ON b.id = a.related
    

    您可能还希望重复这两个查询,以删除 LEFT 关键字(使其成为内部联接而不是外部联接。)

    查看外部联接的一种方法。。。当匹配行来自 B 找到,来自的虚拟行 B 是发明的。该虚拟行完全由空值组成,虚拟行与 A. ,就好像它是一个匹配的行。(这不一定是数据库引擎实际所做的,但这样思考可以让我们深入了解外部联接返回的结果。)

    仔细查看查询的结果,您将能够看到为什么查询的结果不同。


    事实是 A. B 参考同一表格是一种特殊情况。如果这是两个不同的表格,我们会看到相同的结果。真的没关系。。。对于查询,这是两个不同的源,它们恰好引用同一个表。不要让事实 A. B 请参阅同一表格,以免造成混淆。