Sequelize聚合与分组问题:按日期分组指定字段报错
问题解决:按日期分组同时查询明细字段的SQL报错处理
报错原因
SQL语法规则明确:当使用GROUP BY分组时,SELECT列表中的非聚合字段(如price、quantity、product_id)必须要么被包含在GROUP BY子句中,要么被聚合函数(如SUM、MAX)包裹。否则数据库无法确定要返回分组内哪一条数据的对应字段值,因此抛出该错误。
解决方案
根据你的实际业务需求,选择以下两种方案之一:
方案1:按「日期+产品」维度分组(适合需要每日各产品的单独汇总)
如果你的需求是统计每天每个产品的销售总额,同时保留该产品当日的price、quantity(需保证同一产品同一日期的price、quantity是固定值),只需将这些字段加入GROUP BY子句即可:
const productsOfOutgoingInvoice: any = await connection.transaction( async (transaction: Transaction) => { return ProductsOfOutgoingInvoice.findAll({ raw: true, attributes: [ [Sequelize.fn("DATE", Sequelize.col("createdAt")), "date"], [Sequelize.literal("SUM(quantity * price)"), "summ"], "price", "quantity", "product_id" ], group: [ Sequelize.fn("DATE", Sequelize.col("createdAt")), "product_id", "price", "quantity" ], transaction }); } );
此时分组逻辑变为「日期+产品ID+单价+数量」,每个分组对应当日某一产品的销售汇总,同时返回该产品的明细字段。
方案2:保留所有明细记录,同时显示当日总金额(适合需要明细+每日总计)
如果你的需求是保留所有交易明细,同时每条记录附带所属日期的总销售金额,不需要使用GROUP BY,改用SQL窗口函数实现:
const productsOfOutgoingInvoice: any = await connection.transaction( async (transaction: Transaction) => { return ProductsOfOutgoingInvoice.findAll({ raw: true, attributes: [ [Sequelize.fn("DATE", Sequelize.col("createdAt")), "date"], [Sequelize.literal("SUM(quantity * price) OVER (PARTITION BY DATE(createdAt))"), "daily_summ"], "price", "quantity", "product_id", "createdAt" ], transaction }); } );
这里通过OVER (PARTITION BY DATE(createdAt))窗口函数,为每条记录计算其所属日期的总销售金额daily_summ,同时保留所有原始明细字段,无需分组。
内容的提问来源于stack exchange,提问作者Алексей Синельник
相关产品推荐
相关产品推荐

