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

发布于 2024-10-25 16:06:38 字数 357 浏览 1 评论 0原文

请帮助我执行以下 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 字段的空值吗?

Please help me with the following MySQL query, which joins two tables (A and 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 is a field in table A and rYear is a field in table B

The result set is not as expected. Only 185 rows are returned, but there are 629 rows in table A that match the where condition. Shouldn't the rows without a matching row in table B be returned with null values for their B fields?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时光病人 2024-11-01 16:06:38

您不应在 WHERE 子句中指定 rYear。这些限制了您加入后的结果。您应该在 ON 子句中指定 rYear 以从表 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)

You should not specify rYear in a WHERE clause. Those limit your results after the join. You should specify rYear in an ON clause to get back records with NULL from table B.

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)
喜你已久 2024-11-01 16:06:38

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

示例表

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 的查询(第二个选项)适合您,但不适用于您的原始查询。如果没有内部 或 rYear 为 null,情况将会有所不同。

将 LEFT JOIN 想象成这样 [1]

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

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

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

使用 [1] 的输出,根据过滤器进行削减,在左连接之后应用。当 rYear 为 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)

Greg, is that really all there is to the query?

Sample tables

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;

Queries:

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);

Both of the queries are exactly the same, both returning:

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

So I am surprised that Jage's query (the 2nd option) works for you but not your original. It would be different story without the inner or rYear is null.

Think of the LEFT JOIN like this [1]

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

Keep everything in A, and where matched in the ON clause, keep B otherwise pad B columns with NULL. Add the WHERE clause [2]

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

Using the output from [1], CUT down based on the filter, applied AFTER the left join. With the rYear is null, it should still keep all A records, on the proviso that the rCode filter is matched. However, if the filter in rYear is only

AND (rYear in (2011,2012))

It's a different story, because where B was not matched, the rYear was padded with NULL, which won't match the rYear filter -> the entire row gets removed, including the A record. Such a filter on rYear would have gone into the ON clause as shown below, otherwise might as well make it an 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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文