有人可以解释一下为什么这两个查询的输出不同。尝试理解底层逻辑。
查询 - 1
select u.id,
(count(c.id)) comment_count
from users u
left join comments c
on u.id = c.user_id
and c.created_at between '2020-01-01' and '2020-01-31'
group by 1
order by comment_count desc
查询2
select u.id,
(count(c.id)) comment_count
from users u
left join comments c
on u.id = c.user_id
where c.created_at between '2020-01-01' and '2020-01-31'
group by 1
order by comment_count desc
这是 sql 最尖锐的角落之一,也是人们最常犯的错误。
不同的是这个条件
c.created_at between '2020-01-01' and '2020-01-31'
应用于第一个谓词中的 JOIN 谓词
ON .. AND ...
,但应用于第二个谓词中的 WHERE 谓词。
TLDR - 查询 1 实际上执行 LEFT JOIN。查询 2 在功能上是一个 INNER JOIN。如果您在 WHERE 子句中的表 B 上有一个过滤器(除了 NULL 之外的任何内容),那么您是否键入 LEFT JOIN 并不重要,它仍然会表现得像 INNER JOIN。
举这个例子
TableA
a_Key a_Value
1 A
2 B
3 C
TableB
b_Key b_Value b_otherValue
1 A X
2 B Y
所以如果我们加入
SELECT *
FROM TableA A
LEFT
JOIN TableB B
ON A.a_Key = B.b_Key
AND A.a_Value = B.b_Value
结果集将是
a_Key a_Value b_Key b_Value b_otherValue
1 A 1 A X
2 B 2 B Y
3 C NULL NULL NULL
因为在 {3,C} 上没有找到匹配项。
所以当我们在 JOIN 中添加 b_othervalue = 'Y' 时
SELECT *
FROM TableA A
LEFT
JOIN TableB B
ON A.a_Key = B.b_Key
AND A.a_Value = B.b_Value
AND B.b_otherValue = 'Y'
结果是
a_Key a_Value b_Key b_Value b_otherValue
1 A NULL NULL NULL
2 B 2 B Y
3 C NULL NULL NULL
但是,当b_othervalue = 'Y'条件位于WHERE子句中时
SELECT *
FROM TableA A
LEFT
JOIN TableB B
ON A.a_Key = B.b_Key
AND A.a_Value = B.b_Value
WHERE B.b_othervalue = 'Y'
我们得到
a_Key a_Value b_Key b_Value b_otherValue
2 B 2 B Y