ONLY_FULL_GROUP_BY是MySQL提供的一个sql_mode,经过这个sql_mode来提供SQL语句GROUP BY合法性的检查,在MySQL的sql_mode是非ONLY_FULL_GROUP_BY语义时。一条select语句,MySQL容许target list中输出的表达式是除汇集函数或group by column之外的表达式,这个表达式的值可能在通过group by操做后变成undefined,例如:mysql
1
2
3
4
5
6
7
8
9
10
11
12
|
mysql> create database test charset utf8mb4;
mysql> use test;
mysql> create table tt(id int,count int);
mysql> insert into tt values(1,1),(1,2),(2,3),(2,4);
mysql> select * from tt group by id;
+------+-------+
| id | count |
+------+-------+
| 1 | 1 |
| 2 | 3 |
+------+-------+
2 rows in set (0.00 sec)
|
而对于语义限制都比较严谨的多家数据库,如SQLServer、Oracle、PostgreSql都不支持select target list中出现语义不明确的列,这样的语句在这些数据库中是会被报错的,因此从MySQL 5.7版本开始修正了这个语义,就是咱们所说的ONLY_FULL_GROUP_BY语义,例如查看MySQL 5.7默认的sql_mode以下:sql
1
2
|
mysql> select @@global.sql_mode;
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
|
去掉ONLY_FULL_GROUP_BY模式,以下操做:shell
1
|
mysql> set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
|
咱们把刚才的查询再次执行:数据库
1
2
3
|
mysql> select id,count from tt group by id;
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.tt.count' which is
not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
|
刚才经过的查询语句被server拒绝掉了!ide
因此ONLY_FULL_GROUP_BY的语义就是肯定select target list中的全部列的值都是明确语义,简单的说来,在ONLY_FULL_GROUP_BY模式下,target list中的值要么是来自于汇集函数的结果,要么是来自于group by list中的表达式的值。可是因为表达式的表现形式很是丰富,对于程序来讲,很难精确的肯定一些表达式的输出结果是明确的,好比:函数
1
2
3
|
mysql> select count from tt group by id+count,id;
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.tt.count' which is
not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
|
在上面的查询语句中,其实count的值也是能被惟一肯定的,可是因为程序没法分析出这种复杂的关系,因此这条查询也被拒绝掉了。工具
咱们来看下哪些语句是在mysql的ONLY_FULL_GROUP_BY模式下是被支持的。this
1
2
3
4
5
6
7
8
|
mysql> select id+1 from tt group by id+1;
+------+
| id+1 |
+------+
| 2 |
| 3 |
+------+
2 rows in set (0.00 sec)
|
这条语句target list中的id+1和group by中的id+1是严格匹配的,因此mysql认为target list中的id+1是语义明确的,所以该语句能够经过。spa
但下面这条就没法经过了。命令行
1
2
3
|
mysql> select id+1 from tt group by 1+id;
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.tt.id' which is
not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
|
所以,若是查询语句中的target list, having condition 或者order by list里引用了的表达式不是汇集函数,可是和group by list中的表达式严格匹配,该语句也是合法的(id+1和id+1是严格匹配的,id+1和id+2在mysql认为是不严格匹配的, id+1和1+id也是不严格匹配的)。
1
2
3
|
mysql> select id,max(count) from tt group by count;
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.tt.id' which is
not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
|
这条query被server拒绝掉了,由于target list中的id没有出如今汇集函数中,而且也没有出如今group by list中。
看下面这条语句:
1
2
3
4
5
6
7
8
|
mysql> select id+1 as a from tt group by a order by id+1;
+------+
| a |
+------+
| 2 |
| 3 |
+------+
2 rows in set (0.00 sec)
|
mysql容许target list中对于非汇集函数的alias column被group by、having condition以及order by语句引用(version 5.7中容许having condition引用alias column,version 5.6不支持having condition引用alias column),从上面两条语句能够看出,group by和order by中引用了alias column,而且其等价于基础列语义。
1
2
3
4
5
6
7
8
9
10
|
mysql> select id+count from tt group by id,count;
+----------+
| id+count |
+----------+
| 2 |
| 3 |
| 5 |
| 6 |
+----------+
4 rows in set (0.00 sec)
|
从上面的语句能够看出,mysql的ONLY_FULL_GROUP_BY模式支持对basic column进行组合可是不支持对于复杂表达式进行组合,这个受限于表达式分析程度。
总结一下:
MySQL对于ONLY_FULL_GROUP_BY语义的判断规则是,若是group by list中的表达式是basic column,那么target list中容许出现表达式是group by list中basic column或者alias column的组合结果,若是group by list中的表达式是复杂表达式(非basic column或者alias column),那么要求target list中的表达式必须可以严格和group by list中的表达式进行匹配,否者这条查询会被认为不合法。
mysql命令gruop by报错this is incompatible with sql_mode=only_full_group_by
在mysql 工具 搜索或者插入数据时报下面错误:
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'database_tl.emp.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
缘由:
看一下group by的语法:
select 选取分组中的列+聚合函数 from 表名称 group by 分组的列
从语法格式来看,是先有分组,再肯定检索的列,检索的列只能在参加分组的列中选。
我当前Mysql版本5.7.17,
再看一下ONLY_FULL_GROUP_BY的意思是:对于GROUP BY聚合操做,若是在SELECT中的列,没有在GROUP BY中出现,那么这个SQL是不合法的,由于列不在GROUP BY从句中,也就是说查出来的列必须在group by后面出现不然就会报错,或者这个字段出如今聚合函数里面。
查看mysql版本命令:select version();
查看sql_model参数命令:
SELECT @@GLOBAL.sql_mode;
SELECT @@SESSION.sql_mode;
发现:
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
第一项默认开启ONLY_FULL_GROUP_BY,
解决方法:
1.只选择出如今group by后面的列,或者给列增长聚合函数;(不推荐)
2.命令行输入:
set @@GLOBAL.sql_mode='';
set sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
默认关掉ONLY_FULL_GROUP_BY!
这个时候 在用工具select 一下
SELECT @@sql_mode;
SELECT @@GLOBAL.sql_mode;
发现已经不存在ONLY_FULL_GROUP_BY ,感受已经OK。可是若是你重启Mysql服务的话,发现ONLY_FULL_GROUP_BY仍是会存在的
想要完全解决这个问题 就得去改my.ini 配置(若是大家mysql 没有这个文件,就把my-default.ini 改为my.ini,我这个版本就是没有my.ini配置问题)
在 [mysqld]和[mysql]下添加
SET sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE