MySQL交易表按交易类型计算用户净积分的分组查询编写
用户维度净总积分统计MySQL查询实现
最优实现(全MySQL版本兼容,单次扫描表性能最优)
SELECT app_id, user_id, SUM(CASE WHEN tr_type = 'add' THEN points ELSE -points END) AS net_total_points FROM TableA GROUP BY app_id, user_id;
逻辑说明
- 仅对
tr_type取值做条件判断:增加类交易(add)直接累加积分值,扣减类交易(sub)取积分负值后累加,最终累加结果即为该维度下的净总积分 - 分组维度为
app_id、user_id,符合同一应用下同一用户的统计要求,无需将原始points字段加入分组,因为points是聚合计算的对象而非分组维度
常见误区
- 不要将原始
points字段加入GROUP BY子句:如果按points分组,会得到同一用户下不同积分值的零散统计结果,无法计算出整体的净总积分 - 无需多次扫描表做增、减积分的分别统计:条件聚合写法仅需遍历一次全表,性能远高于子查询关联方案
兼容NULL值的健壮版本
若points字段可能存在空值,可加IFNULL规避计算异常:
SELECT app_id, user_id, SUM(CASE WHEN tr_type = 'add' THEN IFNULL(points, 0) ELSE -IFNULL(points, 0) END) AS net_total_points FROM TableA GROUP BY app_id, user_id;
扩展兼容场景
如果后续tr_type可能新增其他取值(比如过期、调账等不计入净积分的类型),可以在CASE逻辑中新增分支做兼容,避免异常值影响统计结果:
SELECT app_id, user_id, SUM( CASE tr_type WHEN 'add' THEN IFNULL(points, 0) WHEN 'sub' THEN -IFNULL(points, 0) ELSE 0 END ) AS net_total_points FROM TableA GROUP BY app_id, user_id;
不推荐的实现方案
如果采用子查询分别统计增、减积分后关联的写法,需要两次扫描全表,性能较差,且处理只有扣减/只有增加记录的用户时需要额外做关联兼容,复杂度远高于上述条件聚合方案,无特殊场景不建议使用。
内容的提问来源于stack exchange,提问作者Venkatasivaramireddy.Venna
相关产品推荐
相关产品推荐

