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