首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用不同的ON从句理解自我连接

用不同的ON从句理解自我连接
EN

Stack Overflow用户
提问于 2018-04-20 15:35:42
回答 2查看 57关注 0票数 0

这是我的桌子结构:

代码语言:javascript
复制
// mytable
+----+---------+----------+
| id | related | subject  |
+----+---------+----------+
| 1  | NULL    | subject1 |
| 2  | 1       |          |
+----+---------+----------+

在我看来,有两个查询看起来是相同的,但是在测试中不同的结果:

代码语言:javascript
复制
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 |
    +----+----------+

看,这是self-join。那么为什么ON a.id = b.relatedON b.id = a.related的结果是不同的呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-04-20 15:56:16

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

这两个查询都是对b进行外部连接。

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

(查询可能看起来是相同的,但事实是它们有很大的不同。)

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

代码语言:javascript
复制
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子句

代码语言:javascript
复制
    ON b.id = a.related

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

一种看待外部连接的方法..。当找不到来自b的匹配行时,就会发明来自b的虚拟行。该虚拟行完全由空值组成,虚拟行被连接到a,就好像它是一个匹配的行。(这并不一定是数据库引擎实际做的事情,但通过这种方式,我们可以了解外部联接返回的结果。)

仔细查看查询的结果,您将能够了解查询的结果为何不同。

ab引用同一个表是一个特例。如果是两个不同的表格,我们就会看到同样的结果。这真的不重要..。对于查询,这是两个不同的源,它们恰好引用同一个表。不要让ab引用同一个表这一事实造成任何混淆。

票数 1
EN

Stack Overflow用户

发布于 2018-04-20 15:45:47

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

您的第一个查询:

代码语言:javascript
复制
SELECT *
FROM mytable a
LEFT JOIN mytable b ON a.id = b.related;

产生以下情况:

代码语言:javascript
复制
+----+---------+----------+--------+----------+----------+
| id | related | subject  |  id1   | related1 | subject1 |
+----+---------+----------+--------+----------+----------+
|  2 | 1       | <null>   | <null> | <null>   | <null>   |
|  1 | <null>  | subject1 | 2      | 1        | <null>   |
+----+---------+----------+--------+----------+----------+

您的第二个查询:

代码语言:javascript
复制
SELECT *
FROM mytable a
LEFT JOIN mytable b ON b.id = a.related;

产生这种情况:

代码语言:javascript
复制
+----+---------+----------+--------+----------+----------+
| id | related | subject  |  id1   | related1 | subject1 |
+----+---------+----------+--------+----------+----------+
|  2 | 1       | <null>   | 1      | <null>   | subject1 |
|  1 | <null>  | subject1 | <null> | <null>   | <null>   |
+----+---------+----------+--------+----------+----------+

第一个查询是将id 2连接到相关的2。没有相关的2,而且由于id 2没有主题,所以您的ifnull()中没有subject

第二个查询是将相关的1加入到id 1 for a.id 2。这从b.id 1中提取了一个主题,结果得到一个id 2的主题。

您确实需要在这里思考LEFT JOIN是如何工作的,以及它是如何受到ON子句的影响的。因此,这里有两个非常不同的查询。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49945210

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档