请帮我处理以下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字段的空值吗?
答案 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)