用不同的on子句理解self-join

9nvpjoqh  于 2021-06-21  发布在  Mysql
关注(0)|答案(2)|浏览(383)

这个问题在这里已经有答案了

了解左连接中匹配行的数量(5个答案)
两年前关门了。
这是我的表格结构:

// 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 有什么不同?

apeeds0o

apeeds0o1#

使用运行查询 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>   |
+----+---------+----------+--------+----------+----------+

您的第一个查询是joining id 2 相关 2 . 没有相关的 2 自从我 2 没有主题,你得不到 subject 从你的 ifnull() .
您的第二个查询与加入相关 1 收件人id 1 对于a.id 2 . 这是一个 subject 来自b.id 1 你要回一个身份证 2 因此。
你真的得在脑子里想清楚 LEFT JOIN 在这里工作以及它是如何受到 ON 条款。因此,这里有两个非常不同的查询。

ecbunoof

ecbunoof2#

两个查询都从中获取所有行 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 请参阅同一表格,以免混淆。

相关问题