MySQL Left Join不为连接表返回空值

时间:2011-03-24 21:55:18

标签: mysql join null

请帮我处理以下MySQL查询,它连接两个表(A和B):

SELECT * from A
left join B on A.sid = B.sid
where (rCode = 1 Or rCode = 2 Or rCode = 3 Or rCode = 5)
AND (rYear = 2011 or rYear is null)

roleCode是表A中的字段,rYear是表B中的字段

结果集与预期不符。仅返回185行,但表A中有629行与where条件匹配。不应该在表B中没有匹配行的行返回其B字段的空值吗?

2 个答案:

答案 0 :(得分:51)

您不应在WHERE子句中指定Year。这些限制了您在加入后的结果。您应该在ON子句中指定Year以从表B中获取带有NULL的记录。

SELECT * from A
left join B 
on A.sid = B.sid 
AND (rYear = 2011 or rYear is null)
where (rCode = 1 Or rCode = 2 Or rCode = 3 Or rCode = 5)

答案 1 :(得分:1)

格雷格,这真的是查询的全部内容吗?

示例表

create table A(rCode int, sid int);
insert A select 1,1;
insert A select 2,3;
insert A select 3,2;
insert A select 5,4;
insert A select 1,5;
create table B(rYear int, sid int);
insert B select 2011,1;
insert B select null,3;
insert B select 2011,2;
insert B select 2015,2;

查询:

SELECT * from A
left join B on A.sid = B.sid
where (rCode = 1 Or rCode = 2 Or rCode = 3 Or rCode = 5)
AND (rYear = 2011 or rYear is null);

SELECT * from A
left join B on A.sid = B.sid AND (rYear = 2011 or rYear is null)
where (rCode = 1 Or rCode = 2 Or rCode = 3 Or rCode = 5);

两个查询完全相同,都返回:

rCode       sid         rYear       sid
----------- ----------- ----------- -----------
1           1           2011        1
2           3           NULL        3
3           2           2011        2
5           4           NULL        NULL
1           5           NULL        NULL

所以我很惊讶Jage的查询(第二个选项)适合你但不适合你原创。如果没有内部or rYear is null,那将是不同的故事。

想想LEFT JOIN就像这样[1]

SELECT * from A
left join B on A.sid = B.sid

将所有内容保存在A中,并且在ON子句中匹配的地方,保留B,否则将B列填充为NULL。添加WHERE子句[2]

where (rCode = 1 Or rCode = 2 Or rCode = 3 Or rCode = 5)
AND (rYear = 2011 or rYear is null);

使用[1]的输出,基于滤波器向下CUT,在左连接后应用。对于rYear is null,它仍应保留所有A记录,条件是rCode过滤器匹配。但是,如果rYear中的过滤器仅为

AND (rYear in (2011,2012))

这是一个不同的故事,因为在B不匹配的情况下,rYear用NULL填充,这与rYear过滤器不匹配 - >整个行被删除,包括A记录。 rYear上的这样一个过滤器会进入ON子句,如下所示,否则也可以使它成为一个INNER JOIN。

SELECT * from A
left join B on A.sid = B.sid AND (rYear in (2011,2012))
where (rCode = 1 Or rCode = 2 Or rCode = 3 Or rCode = 5)