MySQL中SUM用DISTINCT无效,关联查询统计数据异常求助
解决SQL多表关联导致评论数翻倍的问题
这个问题我太熟悉了——你遇到的是SQL多表关联产生笛卡尔积的经典坑!
问题原因分析
当你同时用LEFT JOIN把likes和comentarios两张表关联到posts时,数据库会生成两张表的笛卡尔积:每一条点赞记录都会和该帖子的所有评论记录做组合。比如你有2条点赞、3条评论,关联后会生成2×3=6条记录。你的点赞数用了COUNT(DISTINCT likes.user),所以能得到正确的2;但评论数用SUM(CASE ...)时,每条评论会被重复计算(次数等于点赞数),所以最终得到6,正好是你看到的结果。
之前你尝试在SUM后加DISTINCT没用,是因为SUM(DISTINCT ...)会对CASE返回的1/0去重,结果要么是1要么是0,完全不符合统计需求。
两种可行的解决方案
方案1:子查询分别统计(推荐,性能更优)
先分别统计每个帖子的点赞数和有效评论数,再关联到主表,从根源避免笛卡尔积:
SELECT p.id, COALESCE(l.likes_count, 0) AS likes_count, COALESCE(c.comentarios_count, 0) AS comentarios_count FROM posts p LEFT JOIN ( -- 先统计每个帖子的点赞数 SELECT post, COUNT(DISTINCT user) AS likes_count FROM likes GROUP BY post ) l ON l.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 ) c ON c.foto = p.id;
这里用COALESCE是为了处理那些没有点赞或评论的帖子,确保返回0而不是NULL。
方案2:用COUNT(DISTINCT)统计评论ID
如果不想改结构,也可以对评论的唯一ID去重统计,抵消笛卡尔积的影响:
SELECT p.id, COUNT(DISTINCT likes.user) AS likes_count, COUNT(DISTINCT CASE WHEN comentarios.`delete` = 0 THEN comentarios.id END) AS comentarios_count FROM posts p LEFT JOIN likes ON likes.post = p.id LEFT JOIN comentarios ON comentarios.foto = p.id GROUP BY p.id;
注意:这种方法虽然简单,但性能不如方案1,因为关联后还是会生成大量重复记录,再通过去重统计,数据量大时会拖慢查询速度。
内容的提问来源于stack exchange,提问作者RGS
相关产品推荐
相关产品推荐

