这是我的表结构:
// 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 |
+----+----------+
看,它是自我 -join。那么为什么ON a.id = b.related
和ON b.id = a.related
的结果不同呢?
答案 0 :(得分:3)
使用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()
。
您的第二个查询是将a.id 1
的相关1
加入ID 2
。这会从b.id subject
中提取1
,结果会返回一个标识为2
的主题。
您必须在心理上确定LEFT JOIN
如何在此处工作以及它如何受您的ON
子句影响。结果,您有两个非常不同的查询。
答案 1 :(得分:1)
两个查询都从a
获取所有行。
两个查询都在进行外部加入b
。
用于寻找&#34;匹配&#34;的条件不同。来自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
的虚拟行。该虚拟行完全由NULL值组成,虚拟行与a
连接,就好像它是匹配的行一样。 (这不一定是数据库引擎实际执行的操作,但以这种方式思考它可以让我们深入了解外连接返回的结果。)
仔细查看查询结果,您将能够看到查询结果不同的原因。
a
和b
引用同一个表的事实是一个特例。如果那些是两个不同的表,我们会看到相同的结果。对于查询而言,这并不重要......这些是两个不同的来源,恰好引用同一个表。不要让a
和b
引用同一个表格的事实引起任何混淆。