在Mysql中生成不同输出的逻辑

50few1ms  于 2023-11-16  发布在  Mysql
关注(0)|答案(1)|浏览(122)

有人能解释一下为什么这两个查询的输出不同吗?试着理解潜在的逻辑。
查询-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

ryevplcw

ryevplcw1#

这是sql最尖锐的角落之一,也是人们最常犯的错误。
不同的是这个条件c.created_at between '2020-01-01' and '2020-01-31'
在第一个JOIN predicate ON .. AND ...中应用,但在第二个WHERE predicate 中应用。
TLDR -查询1实际上执行了一个LEFT JOIN。查询2在功能上是一个INNER JOIN。如果你在WHERE子句中对表B有一个过滤器(除了NULL),那么你是否输入LEFT JOIN并不重要,它仍然会表现得像一个INNER JOIN。
一个粗略的解释是,在LEFT JOIN子句中应用的过滤器应用于外部表。但是在WHERE子句中应用的过滤器应用于连接的结果。对于INNER JOIN,这不会影响任何东西,但是对于LEFT 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

相关问题