最近把本地的 MySQL升级到 8.4.5,启动项目后,有好几个 GROUP BY 语句报错了。
几个报错的语句大致都长这样:
select field_name1,field_name2,field_name3,count(field_name4)
from table_name
group by field_name1
报错信息如下:
1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'uid' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
大概意思是查询语句和 sql_mode 不兼容。
SQL 模式中有一个配置模式: ONLY_FULL_GROUP_BY,该模式要求:所有非聚合列必须包含在 GROUP BY 子句中。
来确认一下,我的SQL 模式中是否包含了 ONLY_FULL_GROUP_BY 这个模式。
SELECT @@GLOBAL.sql_mode;
第一个模式就是。
怎么解决呢?办法有很多。
第一种:关闭 ONLY_FULL_GROUP_BY
一不做二不休,直接关闭它,让它报错。
set sql_mode=''
这种方法简单粗暴,绕过限制,但不安全。
可不敢这样做。
另外这样设置一下,数据库重启后,这个参数就失效了。
第二种:把非聚会类都放到 GROUP BY 子句里
提示说,我没有把非聚合列都放到 GROUP BY 子句里,那我就加一下,调整后的语句为:
select field_name1,field_name2,field_name3,count(field_name4)
from table_name
group by field_name1,field_name2,field_name3
听话照做,它说我哪里错了,我就改哪里,修改后保证 sql 畅通运行。
第三种:使用ANY_VALUE关键字
调整后的语句为:
select field_name1,ANY_VALUE(field_name2),ANY_VALUE(field_name3),count(field_name4)
from table_name
group by field_name1
ANY_VALUE 是 MySQL 8.0 及以上版本引入的一个 SQL 关键字,它主要用于 GROUP BY 查询中的聚合操作,特别是在某些情况下允许返回任意值而不违反 ONLY_FULL_GROUP_BY 模式的严格要求。
在启用ONLY_FULL_GROUP_BY模式时,MySQL 要求查询中的非聚合列必须出现在GROUP BY子句中,或者使用聚合函数进行处理。这确保了查询结果的一致性和可预见性。
但是在实际应用中,某些查询中我们可能并不关心某个分组的具体值,只要从每个组中返回任意一个符合条件的值即可。
为了解决这个问题,MySQL 引入了ANY_VALUE()函数,它可以告诉 MySQL “在这个分组内,我对某些列的具体值不关心,只要返回其中的一个值就行”。这样,查询就可以通过ANY_VALUE()来避免违反ONLY_FULL_GROUP_BY模式的错误。
当查询中包含多个非聚合字段,但又不想修改GROUP BY子句时,ANY_VALUE()让 MySQL 不会因为这些字段未聚合而抛出错误。
好在这样的查询语句不是很多,第二种、第三种看看需要哪种解决办法更适合吧。