多表关联查询中SUM忽略DISTINCT导致计算值错误问题
解决一对多关联下SUM主表字段重复计算的问题
问题根源
ordem_servico与fluxo_servico_time是一对多关联关系,关联查询时主表的单条记录会被子表的多条记录重复带出,直接对ordem_servico.cm_total求和会导致同一主表记录的数值被多次累加,最终结果偏大。
可行解决方案
方案1:先聚合主表,再关联子表
先单独计算主表的SUM值,再和子表的统计结果关联,从根源避免重复累加:
SELECT fst.qty, fst.user_id, os.total_cm FROM ( -- 先计算主表的正确总和 SELECT SUM(cm_total) AS total_cm FROM ordem_servico -- 可添加主表过滤条件 ) os JOIN ( -- 子表单独统计需要的qty、user_id SELECT COUNT(*) AS qty, user_id FROM fluxo_servico_time -- 关联主表的外键过滤(按需添加) WHERE ordem_servico_id IN (SELECT id FROM ordem_servico) GROUP BY user_id ) fst ON 1=1 WHERE fst.user_id = 5;
方案2:用子查询独立计算主表总和
在SELECT语句中通过子查询单独计算主表的SUM值,不受关联后的重复记录影响:
SELECT COUNT(fst.id) AS qty, fst.user_id, -- 子查询直接计算主表的正确总和 (SELECT SUM(cm_total) FROM ordem_servico) AS total_cm FROM fluxo_servico_time fst WHERE fst.user_id = 5 GROUP BY fst.user_id;
如果需要按单条主表记录关联统计,可给子查询添加WHERE id = fst.ordem_servico_id条件。
方案3:基于主表主键去重求和
若必须在关联查询中求和,可利用主表唯一主键确保每条记录只被计算一次:
SELECT COUNT(fst.id) AS qty, fst.user_id, -- 用主键+数值的唯一组合去重后计算总和 SUM(DISTINCT os.id * os.cm_total) / SUM(DISTINCT os.id) AS total_cm FROM ordem_servico os JOIN fluxo_servico_time fst ON os.id = fst.ordem_servico_id WHERE fst.user_id = 5 GROUP BY fst.user_id;
原理是通过主键与数值的乘积保证唯一性,求和后除以去重后的主键总数,还原正确的总和。
效果验证
以上方案均可避免主表记录的重复累加,根据实际业务的过滤、分组需求选择对应写法后,即可得到正确的total CM值4328。
内容的提问来源于stack exchange,提问作者Andrei Brayer
相关产品推荐
相关产品推荐

