Mysql 中生成不同输出的逻辑

问题描述 投票:0回答:1

有人可以解释一下为什么这两个查询的输出不同。尝试理解底层逻辑。

查询 - 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 mysql filtering
1个回答
0
投票

这是 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
© www.soinside.com 2019 - 2024. All rights reserved.