如何将含MAX()、INNER JOIN、GROUP BY的SQL转换为Sequelize语法?
解决Sequelize转换含MAX、INNER JOIN、GROUP BY的SQL问题
你当前的问题出在用include处理聚合字段,Sequelize的include默认会生成嵌套关联或额外子查询,不符合你需要的直接JOIN后聚合的逻辑。以下是修正后的代码:
const discussions = await dbUtil.Discussion.findAll({ attributes: [ 'id', 'name', 'open', [Sequelize.fn('MAX', Sequelize.col('Messages.date')), 'last_message_date'] ], include: [{ model: dbUtil.Message, attributes: [], // 不需要返回Message的任何字段 required: true // 等同于INNER JOIN }], where: { forum_id: forumId }, group: ['Discussion.id', 'Discussion.name', 'Discussion.open'], // 严格遵循SQL标准需包含所有非聚合SELECT字段(若数据库允许仅按主键分组可简化) order: [[Sequelize.literal('last_message_date'), 'DESC']], offset, limit: PAGE_LIMIT });
关键修改点:
- 把聚合函数
MAX()移到主模型Discussion的attributes中,用Sequelize.col('Messages.date')明确指定关联表字段(Sequelize会自动给表加别名Messages) include里设置attributes: []避免返回Message冗余字段,required: true确保是INNER JOINgroup字段需包含所有SELECT中未被聚合的字段(部分数据库如MySQL关闭ONLY_FULL_GROUP_BY时可仅按主键分组,但严格遵循SQL标准需列出所有非聚合字段)- 添加
order配置,按生成的last_message_date降序排序
生成的SQL将匹配你的需求:
大致结构如下:
SELECT "Discussion"."id", "Discussion"."name", "Discussion"."open", MAX("Messages"."date") AS "last_message_date" FROM "discussions" AS "Discussion" INNER JOIN "messages" AS "Messages" ON "Discussion"."id" = "Messages"."discussion_id" WHERE "Discussion"."forum_id" = 2 GROUP BY "Discussion"."id", "Discussion"."name", "Discussion"."open" ORDER BY last_message_date DESC LIMIT 20 OFFSET 0
内容的提问来源于stack exchange,提问作者Raphael
相关产品推荐
相关产品推荐

