(transfer) MySQL 5.7 default ONLY_FULL_GROUP_BY semantic introduction

http://www.ywnds.com/?p=8184
ONLY_FULL_GROUP_BY is a sql_mode provided by MySQL. This sql_mode is used to check the validity of SQL statement GROUP BY, when MySQL's sql_mode is not ONLY_FULL_GROUP_BY semantics. A select statement. MySQL allows the expression output in the target list to be an expression other than aggregate function or group by column. The value of this expression may become undefined after the group by operation, for example:


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)
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)
and strict semantic restrictions Many databases, such as SQLServer, Oracle, and PostgreSql, do not support columns with ambiguous semantics in the select target list. Such statements will be reported incorrectly in these databases, so the semantics have been corrected since MySQL version 5.7, which is What we call ONLY_FULL_GROUP_BY semantics, for example, see the default sql_mode of MySQL 5.7 as follows:


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
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模式,如下操作:


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
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';
我们把刚才的查询再次执行:


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
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拒绝掉了!

Therefore, the semantics of ONLY_FULL_GROUP_BY is to determine that the values ​​of all columns in the select target list are clear semantics. In short, in the ONLY_FULL_GROUP_BY mode, the values ​​in the target list are either from the result of the aggregate function or from the group by The value of the expression in the list. However, due to the rich expressions of expressions, it is difficult for the program to accurately determine that the output results of some expressions are clear, for example:


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
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
In the above query statement, the value of count can also be uniquely determined, but because the program cannot analyze this complex relationship, so this The query was also rejected.

Let's see which statements are supported in mysql's ONLY_FULL_GROUP_BY mode.


mysql> select id+1 from tt group by id+1;
+------+
| id+1 |
+------+
| 2 |
| 3 |
+------+
2 rows in set (0.00 sec)
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)
The id+1 in the target list of this statement and the id+1 in the group by are strictly matched, so mysql thinks that the id+1 in the target list is semantically clear, so the statement can be passed.

But the following one cannot pass.


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
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
Therefore, if the expression referenced in target list, having condition or order by list in the query statement is not an aggregate function, but strictly matches the expression in group by list, the statement is also valid (id+1 and id+ 1 is a strict match, id+1 and id+2 are not strictly matched in MySQL, and id+1 and 1+id are also not strictly matched).


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
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
The query was rejected by the server because the id in the target list did not appear in the aggregate function, nor did it appear in the group by list.

Look at the following statement:


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)
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 allows the alias column of the non-aggregate function in the target list to be referenced by group by, having condition and order by statements (version 5.7 allows having condition to reference alias column, version 5.6 does not support having condition to reference alias column), from the above two statements It can be seen that the alias column is referenced in group by and order by, and it is equivalent to the underlying column semantics.


mysql> select id+count from tt group by id,count;
+----------+
| id+count |
+----------+
| 2 |
| 3 |
| 5 |
| 6 |
+----------+
4 rows in set (0.00 sec)
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)
As can be seen from the above statement Out, the ONLY_FULL_GROUP_BY mode of mysql supports the combination of basic columns but does not support the combination of complex expressions, which is limited by the degree of expression analysis.

To sum up:

MySQL's judgment rule for ONLY_FULL_GROUP_BY semantics is that if the expression in the group by list is a basic column, then the allowed expression in the target list is the combination result of the basic column or alias column in the group by list, if the group by list The expression in is a complex expression (non-basic column or alias column), then the expression in the target list must be able to strictly match the expression in the group by list, otherwise the query will be considered illegal.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326102387&siteId=291194637