MySQL查询问题:点赞数导致评论数被相乘如何解决?
问题分析与修复方案
你遇到的这个问题其实是多表关联查询里很常见的「笛卡尔积」坑,咱们一步步拆解:
为什么评论数会被点赞数相乘?
你的查询同时对likes和comentarios两个表做了Left Join,这俩表和posts都是一对多的关系——一个帖子能有N个点赞、M条评论。当一个帖子同时有多个点赞和评论时,Join操作会把每条点赞和每条评论都组合成一行数据,也就是生成N×M行的结果集。
举个实际的例子:某帖子有2个点赞、2条评论,Join后就会出现4行数据。这时候你用SUM(CASE comentarios.delete WHEN 0 THEN 1 ELSE 0 END)统计评论数时,每条评论都会被重复统计2次(对应2个点赞),最终结果自然就变成了2×2=4,和你看到的现象完全吻合。
怎么修复这个问题?
核心思路是把点赞数和评论数的统计分开,用子查询独立计算,避免两个一对多表直接Join产生笛卡尔积。修改后的查询语句如下:
SELECT c.nome, p.foto, c.user, p.user, p.id, p.data, p.titulo, p.youtube, pp.foto, COALESCE(likes_stats.likes_count, 0) AS likes_count, COALESCE(comentarios_stats.comentarios_count, 0) AS comentarios_count, COALESCE(user_like.exists_like, 0) AS count2 FROM posts p JOIN cadastro c ON p.user = c.id LEFT JOIN profile_picture pp ON p.user = pp.user -- 子查询单独统计每个帖子的总点赞数 LEFT JOIN ( SELECT post, COUNT(DISTINCT user) AS likes_count FROM likes GROUP BY post ) likes_stats ON likes_stats.post = p.id -- 子查询单独统计每个帖子未被删除的评论数 LEFT JOIN ( SELECT foto, SUM(CASE WHEN `delete` = 0 THEN 1 ELSE 0 END) AS comentarios_count FROM comentarios GROUP BY foto ) comentarios_stats ON comentarios_stats.foto = p.id -- 子查询判断用户(user='1')是否给该帖子点过赞 LEFT JOIN ( SELECT post, 1 AS exists_like FROM likes WHERE user = '1' ) user_like ON user_like.post = p.id GROUP BY p.id ORDER BY p.id DESC LIMIT 10;
几个关键细节说明:
- 子查询隔离统计:把点赞、评论的统计放到独立子查询里,每个子查询单独按帖子分组计算,彻底避免了多表Join带来的重复行问题。
- COALESCE函数:处理那些没有点赞或评论的帖子,把NULL结果转成0,确保统计数字更合理。
- 关键字转义:
delete是MySQL的关键字,所以用反引号`包裹,避免语法报错(原查询里这里其实有潜在风险)。 - 简化用户点赞判断:原来的
count(DISTINCT l2.user)改成了子查询判断是否存在,返回1或0,逻辑更清晰,性能也更好。
内容的提问来源于stack exchange,提问作者RGS
相关产品推荐
相关产品推荐

