SQL转Sequelize查询异常:仅返回单条数据,求修正方案
问题修正:SQL转Sequelize代码错误导致结果异常
原SQL逻辑
SELECT sum(document_details.qty) 'miktar', stocks.id, stocks.`name` FROM document_details INNER JOIN documents ON documents.id = document_details.document_id INNER JOIN stocks ON document_details.stock_id = stocks.id WHERE documents.warehouse_id = 1 GROUP BY document_details.stock_id
原代码的核心问题
- 错误以
Documents作为查询主模型,和原SQL逻辑不符:原SQL以document_details为基础做关联聚合,从Documents查询会导致结果按文档分组,而非按库存ID分组。 - 分组条件写在
include的子模型配置中,不符合Sequelize聚合查询逻辑,主查询的分组需统一配置在顶层group选项。 - 未正确关联
Stocks模型并提取对应字段,聚合字段的配置位置错误。
正确的Sequelize实现代码
const { id } = req.query; const { limit, page, sortColumn, sortType, search } = req.body; // 模型关联建议在外部全局定义,避免每次查询重复声明 Documents.hasMany(DocumentsDetail, { foreignKey: "document_id" }); DocumentsDetail.belongsTo(Documents, { foreignKey: "document_id" }); DocumentsDetail.belongsTo(Stocks, { foreignKey: "stock_id" }); // 执行聚合查询 const result = await DocumentsDetail.findAll({ attributes: [ [sequelize.fn('sum', sequelize.col('qty')), 'miktar'], [sequelize.col('Stocks.id'), 'stock_id'], [sequelize.col('Stocks.name'), 'stock_name'] ], include: [ { model: Documents, attributes: [], // 仅用于过滤,不需要返回Documents字段 where: { warehouse_id: id, id: { [Op.substring]: search } // 保留原搜索条件 } }, { model: Stocks, attributes: [] // 需要的字段已在顶层attributes中指定 } ], group: ['document_details.stock_id', 'Stocks.id', 'Stocks.name'], // 分组需包含所有非聚合字段 limit: limit, offset: (page - 1) * limit, order: [[sortColumn || 'Stocks.name', sortType || 'ASC']] // 可按需调整排序字段 }); // 统计分组后的总条数(避免分组对count的影响) const total = await DocumentsDetail.count({ include: [ { model: Documents, where: { warehouse_id: id, id: { [Op.substring]: search } } } ], distinct: true, col: 'stock_id' // 按库存ID去重统计总数 }); res.json({ total: total, data: result, warehouse_name });
关键说明
- 主查询模型改为
DocumentsDetail,与原SQL的查询起点保持一致。 - 聚合函数与关联字段均配置在顶层
attributes中,通过sequelize.col指定完整字段路径。 - 分组条件需包含所有SELECT中的非聚合字段,符合SQL分组规则,避免报错或结果异常。
- 统计总数时使用
distinct和指定col参数,确保得到分组后的正确总条数。
内容的提问来源于stack exchange,提问作者Melike Kozan
相关产品推荐
相关产品推荐

