Sequelize执行查询触发MySQL only_full_group_by报错如何解决
报错产生原因
MySQL 开启 sql_mode=only_full_group_by 校验规则时,要求SELECT列表中出现的所有非聚合列,必须和GROUP BY子句中的列/表达式严格对应,不存在语义歧义才可以正常执行。
你的查询触发报错的核心问题有两处:
- SELECT 列表直接查询了原生的
ingredient列,但GROUP BY的分组依据是LOWER(ingredient)函数计算结果。比如值为Flour和flour的记录会被分到同一个分组,但原生ingredient存在两个不同值,MySQL无法确定该返回哪个值,判定为不符合规则。 - ORDER BY 排序也直接使用了原生
ingredient列,同样和分组表达式不匹配,也会触发校验拦截。
修复方案
根据业务需求选择对应调整方式即可,不推荐直接修改MySQL配置关闭only_full_group_by校验,这种方式会导致查询结果存在不可控的歧义,容易引发业务逻辑错误。
方案1:对齐分组、查询、排序的字段逻辑(推荐)
如果你本来的需求就是按不区分大小写的食材名合并统计采购量,直接把SELECT和ORDER BY的字段都和GROUP BY的LOWER(ingredient)逻辑对齐即可,修正后的Sequelize代码如下:
await UserRecipeItem.findAll({ where: { weekNumber: week, userId: user.id, recipeId: { [OP.in]: shoppingListRecipeList, }, }, attributes: [ // 与分组逻辑保持一致,返回转小写后的食材名 [Sequelize.fn("LOWER", Sequelize.col("ingredient")), "ingredient"], [Sequelize.fn("sum", Sequelize.col("quantity")), "quantityCount"], ], group: [Sequelize.fn("LOWER", Sequelize.col("ingredient"))], // 排序字段与返回字段对齐 order: [[Sequelize.literal("ingredient"), "desc"]], });
调整后生成的SQL会满足only_full_group_by的校验要求,查询结果无歧义。
方案2:明确非分组列的聚合规则
如果你需要保留食材名的原始大小写格式,且业务上可以接受同个大小写不敏感的分组下,返回任意一条记录的原始食材名,可以用MySQL内置的ANY_VALUE()函数包裹非聚合列,明确告知MySQL不需要校验该列的依赖关系,调整方式如下:
await UserRecipeItem.findAll({ where: { weekNumber: week, userId: user.id, recipeId: { [OP.in]: shoppingListRecipeList, }, }, attributes: [ // 用ANY_VALUE明确取该分组下任意一个ingredient值 [Sequelize.fn("ANY_VALUE", Sequelize.col("ingredient")), "ingredient"], [Sequelize.fn("sum", Sequelize.col("quantity")), "quantityCount"], ], group: [Sequelize.fn("LOWER", Sequelize.col("ingredient"))], order: [[Sequelize.fn("ANY_VALUE", Sequelize.col("ingredient")), "desc"]], });
内容的提问来源于stack exchange,提问作者Manish Hedau
相关产品推荐
相关产品推荐

