转载自:https://blog.csdn.net/u012660464/article/details/113977173

  1. 报错原因

MySQL8 对 group by 进行了优化. 他默认启动改进之后的版本启动了 ONLY_FULL_GROUP_BY 模式.

这种模式的官方解释:ONLY_FULL_GROUP_BY是MySQL数据库提供的一个sql_mode, 通过这个 sql_mode 来保证, SQL语句 “分组求最值” 合法性的检查. 这种模式采用了与 Oracle、DB2 等数据库的处理方式。即不允许 select target list 中出现语义不明确的列.
对于用到 GROUP BY 的 select 语句, 查出来的列必须是 group by 后面声明的列, 或者是聚合函数里面的列有这样一个数据库的表.

合 == 合法; 不 == 不合法
(合) select 语句:select id, sum(appr_id) from appr group by id
(合) select 语句:select id, user_id, sum(appr_id) from appr group by id
(不) select 语句:select id, sum(appr_id) from appr group by role
(不) select 语句:select id, user_id, sum(appr_id) from appr group by role
(不) select 语句:select * from appr group by role

经过大量测试:笔者发现了 ONLY_FULL_GROUP_BY 这种模式的特点:

1:只要有聚合函数 sum(),count(),max(),avg() 等函数就需要用到 group by , 否则就会报上面的错误.
2:group by id (id 是主键) 的时候, select 什么都没有问题, 包括有聚合函数.
3:group by role (非主键) 的时候, select 只能是聚合函数和 role ( group by 的字段) , 否则报错

解决方案:

解决方案一:使用函数ANY_VALUE()包含报错字段

将上述报错语句改成:

SELECT ANY_VALUE(ID),USER_ID,ANY_VALUE(problems),ANY_VALUE(last_updated_date) FROM  t_iov_help_feedback GROUP BY USER_ID;

可以看到,结果能正常查询了,根据需要自己改查询字段的别名就行。

ANY_VALUE()函数说明:

MySQL有any_value(field)函数,它主要的作用就是抑制ONLY_FULL_GROUP_BY值被拒绝。
这样sql语句不管是在ONLY_FULL_GROUP_BY模式关闭状态还是在开启模式都可以正常执行,不被mysql拒绝。
any_value()会选择被分到同一组的数据里第一条数据的指定列值作为返回数据。
官方有介绍,地址:https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_any-value

解决方案二:通过sql语句暂时性修改sql_mode

去掉ONLY_FULL_GROUP_BY,重新设置值

SET @@global.sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

上面是改变了全局sql_mode,对于新建的数据库有效。对于已存在的数据库,则需要在对应的数据库下执行:

SET sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

重启mysql数据库服务之后,ONLY_FULL_GROUP_BY还会出现,所以这只是暂时性的。

解决方案三:通过配置文件永久修改sql_mode

mysql安装在服务器上和安装在本地,修改配置文件的方式有点区别。

  1. Linux下修改配置文件
    1)登录进入MySQL
    使用命令 mysql -u username -p 进行登陆,然后输入密码,输入SQL:
    show variables like '%sql_mode';

    2)编辑my.cnf文件
    文件地址一般在:/etc/my.cnf,/etc/mysql/my.cnf
    使用vim命令编辑文件,不知道vim命令怎么使用的,可以参考我的另外篇文章:Linux中使用vi工具进行文本编辑
    找到sql-mode的位置,去掉ONLY_FULL_GROUP_BY
    然后重启MySQL;
    有的my.cnf中可能没有sql-mode,需要追加:

    sql-mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

    注意要加入到[mysqld]下面,如加入到其他地方,重启后也不生效
    3)修改成功后重启MySQL服务

    service mysql restart

    重启好后,再登录mysql,输入SQL:show variables like '%sql_mode'; 如果没有ONLY_FULL_GROUP_BY,就说明已经成功了。
    如果还不行,那么只保留STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION 即可
    追加内容为:

    sql-mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION

    20191122164545550.png

  2. window下修改配置文件
    1)找到mysql安装目录,用记事本直接打开my.ini文件
    2)编辑my.cnf文件,在[mysql]标签下追加内容
    sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

    3)重启mysql 服务
    备注:
    网上有些提供了sql_mode的值,却导致重启mysql服务启动不了

    sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

    这时,只需要将sql_mode 值中 “NO_AUTO_CREATE_USER” 这个属性去掉即可。