MySQL中WHERE与ON子句导致查询结果不同的底层逻辑解析
两个MySQL查询结果不同的底层逻辑解析
核心区别在于:LEFT JOIN的ON条件和WHERE条件执行时机完全不同,这直接决定了最终输出的差异。
查询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
这个查询把时间过滤写在ON子句里:
- 执行
LEFT JOIN时,MySQL会先保留users表的所有记录 - 再匹配
comments表中同时满足「user_id等于用户ID」和「评论时间在2020年1月」的记录 - 对没有符合条件评论的用户,
comments表的所有字段会被填充为NULL - 最后
count(c.id)统计时,NULL会被忽略,所以这类用户的comment_count显示为0
最终查询1会返回所有用户,包括2020年1月没发表评论的用户。
查询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
这个查询把时间过滤移到了WHERE子句:
- 先执行
LEFT JOIN,仅匹配user_id相等的记录,此时所有users记录都会保留,但无评论用户对应的comments字段是NULL - 接着执行
WHERE过滤:c.created_at为NULL的记录(无评论用户),因为NULL和任何时间范围比较结果都是FALSE,会被直接过滤 - 有评论但评论时间不在2020年1月的用户,
JOIN后对应的comments记录也是NULL,同样会被过滤
最终查询2只会返回2020年1月有发表评论的用户,无符合条件评论的用户会被完全排除。
核心差异总结
- 查询1:保留所有用户,无有效评论的用户统计数为0
- 查询2:只保留有有效评论的用户,无有效评论的用户直接被剔除
内容的提问来源于stack exchange,提问作者Uswa Mazhar
相关产品推荐
相关产品推荐

