SQL 左连接行为
SQL LEFT JOIN behaviour
尝试获取 SQL LEFT JOIN 到 return NULL,其中在其他 table 中没有相应的行。
Table 1 - T1
id n
1 aaa
2 bbb
3 ccc
Table 2 - T2
t1_id t3_id
1 1
2 1
3 1
1 2
3 2
2 3
3 3
在T2中,注意没有2-2或1-3的组合。
select *
from t1
left join t2
on t1.id = t2.t1_id
order by t2.t3_id, t1_id
输出:
id n t1_id t3_id
1 aaa 1 1
2 bbb 2 1
3 ccc 3 1
1 aaa 1 2
3 ccc 3 2
2 bbb 2 3
3 ccc 3 3
我原以为还有两行
1 aaa null null
2 bbb null null
...对应T2中前面提到的缺失组合
请注意 ORDER BY 只是为了方便 - 它对 returned 行没有影响。
请帮助我理解为什么会发生这种情况,以及如何解决它。
如果您想要结果集中 t2
中的所有行,它应该是 left join
中引用的第一个 table:
select *
from t2 left join
t1
on t1.id = t2.t1_id
order by t2.t3_id, t2.t1_id;
编辑:
您似乎想要生成 原始数据中没有的新行。使用 cross join
生成行,然后 left join
将它们引入:
select t3.t3_id, t1.id, t1.n
from (select distinct t2.t3_id from t2) as t3 cross join
t1 left join
t2
on t3.t3_id = t2.t3_id and t2.t1_id
或者,如果您确实想在 FROM
中首先引用 t1
,您可以改用 RIGHT JOIN
(我个人觉得这些不太直观,但有些人更喜欢它们,当涉及更多表时,它们确实有它们的用处):
SELECT *
FROM t1
RIGHT JOIN t2 ON t1.id = t2.t1_id
ORDER BY t2.t3_id,
t1_id;
table1:
-------------
| id | name |
-------------
| 1 | john |
-------------
| 2 | mark |
-------------
| 3 | will |
-------------
table2:
-----------------
| t1_id | t3_id |
-----------------
| 1 | 3 |
-----------------
| 1 | 2 |
-----------------
| 3 | 1 |
-----------------
如果我想通过 table2 获取 table1:
SELECT t1.*
FROM table2 as t2
LEFT JOIN table1 as t1
ON t1.id = t2.t1_id
WHERE 1
ORDER BY t1.id ASC;
您将获得:
-------------
| id | name |
-------------
| 1 | john |
-------------
| 1 | john |
-------------
| 3 | will |
-------------
已编辑:
所以查询将得到表2中的所有内容,所以(t1_id: 1, t3_id: 3), (t1_id: 1, t3_id: 2 ), (t1_id: 3, t3_id: 1), 那么left join会将t1的id与t2中的t1_id和t1中的所有列return作为i进行比较写了 *.
尝试获取 SQL LEFT JOIN 到 return NULL,其中在其他 table 中没有相应的行。
Table 1 - T1
id n
1 aaa
2 bbb
3 ccc
Table 2 - T2
t1_id t3_id
1 1
2 1
3 1
1 2
3 2
2 3
3 3
在T2中,注意没有2-2或1-3的组合。
select *
from t1
left join t2
on t1.id = t2.t1_id
order by t2.t3_id, t1_id
输出:
id n t1_id t3_id
1 aaa 1 1
2 bbb 2 1
3 ccc 3 1
1 aaa 1 2
3 ccc 3 2
2 bbb 2 3
3 ccc 3 3
我原以为还有两行
1 aaa null null
2 bbb null null
...对应T2中前面提到的缺失组合
请注意 ORDER BY 只是为了方便 - 它对 returned 行没有影响。
请帮助我理解为什么会发生这种情况,以及如何解决它。
如果您想要结果集中 t2
中的所有行,它应该是 left join
中引用的第一个 table:
select *
from t2 left join
t1
on t1.id = t2.t1_id
order by t2.t3_id, t2.t1_id;
编辑:
您似乎想要生成 原始数据中没有的新行。使用 cross join
生成行,然后 left join
将它们引入:
select t3.t3_id, t1.id, t1.n
from (select distinct t2.t3_id from t2) as t3 cross join
t1 left join
t2
on t3.t3_id = t2.t3_id and t2.t1_id
或者,如果您确实想在 FROM
中首先引用 t1
,您可以改用 RIGHT JOIN
(我个人觉得这些不太直观,但有些人更喜欢它们,当涉及更多表时,它们确实有它们的用处):
SELECT *
FROM t1
RIGHT JOIN t2 ON t1.id = t2.t1_id
ORDER BY t2.t3_id,
t1_id;
table1:
-------------
| id | name |
-------------
| 1 | john |
-------------
| 2 | mark |
-------------
| 3 | will |
-------------
table2:
-----------------
| t1_id | t3_id |
-----------------
| 1 | 3 |
-----------------
| 1 | 2 |
-----------------
| 3 | 1 |
-----------------
如果我想通过 table2 获取 table1:
SELECT t1.*
FROM table2 as t2
LEFT JOIN table1 as t1
ON t1.id = t2.t1_id
WHERE 1
ORDER BY t1.id ASC;
您将获得:
-------------
| id | name |
-------------
| 1 | john |
-------------
| 1 | john |
-------------
| 3 | will |
-------------
已编辑:
所以查询将得到表2中的所有内容,所以(t1_id: 1, t3_id: 3), (t1_id: 1, t3_id: 2 ), (t1_id: 3, t3_id: 1), 那么left join会将t1的id与t2中的t1_id和t1中的所有列return作为i进行比较写了 *.