SQL中如何避免SUM()统计时计算JOIN操作产生的重复行?
解决方法
方案1:窗口函数标记唯一行(推荐,无业务限制)
该方案可保留关联得到的所有business_id字段,同时保证每个wallet的credit仅统计一次:
select wtpa.business_id, sum(case when row_number() over (partition by w.id order by wtpa.id) = 1 then w.credit else 0 end) over () as total_credit from wallet w left join where_to_pay_ability wtpa on w.id = wtpa.wallet_id where w.user_id = 1
逻辑说明:row_number() over (partition by w.id)会给同一个钱包关联出的多条记录按顺序编号,只有编号为1的首行会计入credit求和,其余重复关联行不计入,最终得到的total_credit就是预期的1000,且每一行都保留对应的business_id。
方案2:SUM+DISTINCT简化写法(有适用限制)
如果业务逻辑可保证不同wallet的credit值不会重复,可使用更简洁的写法:
select wtpa.business_id, sum(distinct w.credit) over () as total_credit from wallet w left join where_to_pay_ability wtpa on w.id = wtpa.wallet_id where w.user_id = 1
注意:如果存在两个不同wallet的credit值相同的情况,该方案会出现统计错误,仅适合已知credit不会跨钱包重复的场景。
方案3:EXISTS子查询(仅需统计总credit时使用)
如果不需要将business_id和总credit放在同一行返回,仅需要关联条件做过滤,可以用EXISTS避免JOIN导致的行膨胀:
select sum(credit) from wallet w where user_id = 1 and exists ( select 1 from where_to_pay_ability wtpa where wtpa.wallet_id = w.id )
内容的提问来源于stack exchange,提问作者Mohammad Gholamrezaie
相关产品推荐
相关产品推荐

