如何用Sequelize一次性查询全行并计算amount总和?
单次查询实现总和与行数据的获取
嘿,我懂你现在的需求——不想靠两次查询分别拿数据、算总和,想要一次搞定对吧?这完全可以实现,下面给你两种基于Sequelize的解决方案,看你更倾向哪种:
方案一:使用原生SQL查询(推荐,简洁直接)
这种方式利用数据库的聚合函数和JSON函数,一次查询就能同时拿到总金额和所有行数据:
const [queryResult] = await sequelize.query(` SELECT SUM(amount) AS totalAmount, JSON_ARRAYAGG( JSON_OBJECT( 'amount', amount, 'currency', currency, 'date', date ) ) AS rows FROM users WHERE date = :currentDate AND currency = :currency `, { replacements: { currentDate, currency }, type: sequelize.QueryTypes.SELECT }); // 格式化结果,把总和转成数字,解析JSON数组 const finalResult = { totalAmount: parseInt(queryResult.totalAmount, 10) || 0, rows: JSON.parse(queryResult.rows) || [] };
为什么这个方法可行?
SUM(amount)直接计算符合条件的所有记录的金额总和JSON_ARRAYAGG+JSON_OBJECT把每一行数据转换成JSON对象,再聚合成一个数组- 通过参数替换
replacements避免SQL注入风险
方案二:使用Sequelize模型的子查询方式
如果你更想沿用Sequelize的模型语法,不想写太多原生SQL,可以用子查询来实现:
const queryResult = await user.findOne({ attributes: [ // 外层查询计算总金额 [sequelize.fn('SUM', sequelize.col('amount')), 'totalAmount'], // 子查询获取所有符合条件的行数据,转成JSON数组 [sequelize.literal(`( SELECT JSON_ARRAYAGG( JSON_OBJECT('amount', amount, 'currency', currency, 'date', date) ) FROM users WHERE date = :currentDate AND currency = :currency )`), 'rows'] ], where: { date: currentDate, currency: currency }, replacements: { currentDate, currency }, raw: true }); // 格式化结果 const finalResult = { totalAmount: parseInt(queryResult.totalAmount, 10) || 0, rows: JSON.parse(queryResult.rows) || [] };
注意事项
- 确保你的数据库支持
JSON_ARRAYAGG和JSON_OBJECT函数(比如MySQL 5.7+、MariaDB 10.2+),如果是PostgreSQL,需要替换成array_agg和json_build_object - 如果
amount字段在数据库里是字符串类型,SUM函数会自动尝试转换为数值计算,但建议最好把amount设置为数值类型(比如INT、DECIMAL),避免转换问题 - 如果没有符合条件的记录,
totalAmount会是null,所以我们用|| 0处理成0,rows会是null,处理成空数组
内容的提问来源于stack exchange,提问作者EL TEGANI MOHAMED
相关产品推荐
相关产品推荐

