LEFT JOIN匹配行数解析:为何两次自连接查询结果行数不同
为什么两个看似相似的LEFT JOIN自连接结果行数不同?
嘿,我来帮你彻底搞懂这个问题!核心在于你得先吃透LEFT JOIN的底层工作逻辑,再对比两个查询的匹配条件差异,就能明白为啥行数不一样了。
LEFT JOIN的核心规则
简单来说,LEFT JOIN的逻辑是:
- 以左表(
t1)的每一行作为基础,必须全部保留在结果里 - 针对左表的每一行,去右表(
t2)中找所有满足ON条件的行- 如果找到N行,就会在结果里生成N条对应左表当前行的记录
- 如果找不到匹配的行,就用
NULL填充右表的列,保留左表的这一行
先明确你的表数据,方便后续拆解:
CREATE TABLE mytable ( id int, related int ); INSERT into mytable VALUES(1, NULL); INSERT into mytable VALUES(2, 1); INSERT into mytable VALUES(3, 1);
对应的表内容:
| id | related |
|---|---|
| 1 | NULL |
| 2 | 1 |
| 3 | 1 |
第一个查询:t1.related = t2.id
SELECT t1.id, t2.id FROM mytable as t1 LEFT JOIN mytable as t2 ON t1.related = t2.id;
逐行分析左表t1的匹配情况:
t1.id=1:t1.related是NULL,SQL里NULL和任何值比较都会返回UNKNOWN(不满足匹配条件),所以右表t2没有匹配行,结果生成(1, NULL)t1.id=2:t1.related=1,匹配t2.id=1的行,结果生成(2, 1)t1.id=3:t1.related=1,同样匹配t2.id=1的行,结果生成(3, 1)
总共3行,和你看到的结果一致。
第二个查询:t1.id = t2.related
SELECT t1.id, t2.id FROM mytable as t1 LEFT JOIN mytable as t2 ON t1.id = t2.related;
还是逐行看左表t1的匹配逻辑:
t1.id=1:找t2.related=1的行,右表t2里id=2和id=3的related都是1,所以匹配到2行,结果生成(1, 2)和(1, 3)t1.id=2:找t2.related=2的行,右表里没有符合条件的记录,结果生成(2, NULL)t1.id=3:找t2.related=3的行,右表里也没有匹配项,结果生成(3, NULL)
总共2+1+1=4行,和实际返回的结果一致。
总结
这两个查询的ON条件完全相反:一个是用左表的related字段匹配右表的id,另一个是用左表的id匹配右表的related,匹配逻辑天差地别,自然结果行数不一样。记住LEFT JOIN的核心:左表的每一行都会被保留,右表匹配到多少行就生成多少对应记录,没匹配到就用NULL填充右表列。
内容的提问来源于stack exchange,提问作者Martin AJ
相关产品推荐
相关产品推荐

