Sequelize如何实现带条件Sum聚合并按年月分组查询
Sequelize 分组条件聚合统计佣金方案
你需要实现的是同分组下多条件独立聚合场景,不需要拆分查询,直接在SUM聚合中嵌套条件判断即可实现,不需要额外加having或者子查询。
原有写法问题说明
你之前的代码有两个核心错误:
- 把
is_paid字段放进了查询属性但没有加入分组规则,会触发SQL语法错误;如果把is_paid加入分组,同一月份会被拆成已支付、未支付两条独立记录,无法在单条结果里返回两个状态的统计值 - 两个SUM聚合函数没有加筛选条件,最终计算出的都是分组下全部佣金的总和,两个字段值完全一致,无法区分支付状态
可直接运行的实现代码
const { fn, col, literal } = require('sequelize'); const financeStats = await db.Finanzas.findAll({ attributes: [ // 分组字段起别名,匹配预期返回结构 [col('mes'), 'month'], [col('ano'), 'year'], // 条件聚合:仅统计已支付状态的佣金 [ fn('SUM', literal('CASE WHEN is_paid = 1 THEN agents_commission ELSE 0 END')), 'commission_paid_sum' ], // 条件聚合:仅统计未支付状态的佣金 [ fn('SUM', literal('CASE WHEN is_paid = 0 THEN agents_commission ELSE 0 END')), 'comission_notPaid_sum' ] ], // 注意:按数据库实际存储的月、年字段分组,不要加入is_paid group: ['mes', 'ano'], raw: true });
注意:如果你的
is_paid字段是布尔类型而非tinyint/int类型,把判断条件里的=1/=0替换为= true/= false即可;如果你的月份、年份字段名不是mes/ano,替换成实际字段名即可。
扩展场景方案
如果需要统计的年月范围里存在无数据的月份(比如某月份没有任何佣金记录,也需要返回该月份统计值为0的结果),不能直接用上述分组查询,需要两步处理:
- 先生成你需要统计的所有年月组合的基础数组
- 用上述查询拿到有数据的月份统计结果,遍历基础数组把不存在的月份统计值补0即可
本次查询涉及的Finance数据表结构参考:
内容的提问来源于stack exchange,提问作者AleOjeda
相关产品推荐
相关产品推荐

