MySQL LEFT JOIN关联COUNT结果异常求助(RDS MySQL 8.0.13)
分析LEFT JOIN搭配COUNT结果不符的原因
嘿,我来帮你拆解这三个查询的差异,核心问题出在LEFT JOIN的ON子句和WHERE子句的执行时机不同,以及COUNT函数的统计逻辑上:
1. 第一个查询:SELECT COUNT(p.product_id) FROM product p LEFT JOIN product_attributes pa ON p.pdt_id = pa.pdt_id WHERE pa.code = 'season';(结果6332)
你可能以为这是LEFT JOIN,但实际上WHERE pa.code = 'season'这个条件直接把LEFT JOIN的效果改成了类似INNER JOIN。原因很简单:
- LEFT JOIN会先把product里的所有行和匹配的product_attributes行关联,没有匹配的pa行会用NULL填充。
- 但WHERE子句是在关联完成后过滤行,
pa.code = 'season'会把那些pa为NULL的行(也就是没有对应season属性的product行)全部过滤掉。 - 最后
COUNT(p.product_id)统计的是剩下的、有匹配season属性的product行数,所以结果比总product数少,是6332。
2. 第二个查询:SELECT COUNT(*) FROM product p;(结果6455)
这个很直观,就是统计product表的总行数,也就是所有存在的product数量,作为我们的基准值。
3. 第三个查询:SELECT COUNT(p.product_id) FROM product p LEFT JOIN product_attributes pa ON p.pdt_id = pa.pdt_id AND pa.code = 'season';(结果6455)
这个才是真正保留LEFT JOIN语义的写法:
- 把
pa.code = 'season'放在ON子句里,意味着关联的时候只匹配pa中code为season的行,没有匹配的pa行依然用NULL填充,但不会过滤掉product的行。 COUNT(p.product_id)统计的是product表的所有行(因为p.product_id是product的主键,不会为NULL,哪怕pa行是NULL),所以结果和product总行数一致,是6455。
补充个小细节:如果把第三个查询里的COUNT(p.product_id)换成COUNT(pa.pdt_id),结果就会变成6332——因为pa.pdt_id在没有匹配的时候是NULL,COUNT不会统计NULL值。
内容的提问来源于stack exchange,提问作者pcouaillier
相关产品推荐
相关产品推荐

