MySQL中GROUP BY隐式排序是什么概念呢? 主要是其它RDBMS没有这样的概念,如果没有认真了解过概念,对这个概念会感觉有点困惑,我们先来看看官方文档的介绍:

官方文档MySQL 5.7 Reference Manual中的“.2.1.14 ORDER BY Optimization”章节有如下介绍:

GROUP BY implicitly sorts by default (that is, in the absence of ASC or DESC designators for GROUP BY columns). However, relying on implicit GROUP BY sorting (that is, sorting in the absence of ASC or DESC designators) or explicit sorting for GROUP BY (that is, by using explicit ASC or DESC designators for GROUP BY columns) is deprecated. To produce a given sort order, provide an ORDER BY clause.

默认情况下GROUP BY隐式排序(即,缺少GROUP BY列的ASC或DESC指示符)。但是,不推荐依赖于隐式GROUP BY排序(即,在没有ASC或DESC指示符的情况下排序)或GROUP BY的显式排序(即,通过对GROUP BY列使用显式ASC或DESC指示符)。要生成给定的排序 ORDER,请提供ORDER BY子句。

从MySQL 8.0开始,GROUP BY字段不再支持隐式排序. 官方文档MySQL 8.0 Reference Manual中“8.2.1.16 ORDER BY Optimization”章节有如下介绍:

Previously (MySQL 5.7 and lower), GROUP BY sorted implicitly under certain conditions. In MySQL 8.0, that no longer occurs, so specifying ORDER BY NULL at the end to suppress implicit sorting (as was done previously) is no longer necessary. However, query results may differ from previous MySQL versions. To produce a given sort order, provide an ORDER BY clause.

那么来看看MySQL的GROUP BY隐式排序(GROUP BY sorted implicitly)吧。我们用“Removal of implicit and explicit sorting for GROUP BY”这篇博客中的例子。

下面实验环境为MySQL 5.6.41()

mysql> select version() from dual;

+------------+

| version()  |

+------------+

| 5.6.41-log |

+------------+

1 row in set (0.00 sec)

 

mysql> CREATE TABLE t (id INTEGER,  cnt INTEGER);

Query OK, 0 rows affected (0.04 sec)

 

mysql> INSERT INTO t VALUES (4,1),(3,2),(1,4),(2,2),(1,1),(1,5),(2,6),(2,1),(1,3),(3,4),(4,5),(3,6);

Query OK, 12 rows affected (0.00 sec)

Records: 12  Duplicates: 0  Warnings: 0

#MySQL在这里隐式地对GROUP BY的结果进行排序(即在缺少GROUP BY列的ASC或DESC指示符的情况下)。

mysql> SELECT id, SUM(cnt) FROM t GROUP BY id; --GROUP BY隐式排序

+------+----------+

| id   | SUM(cnt) |

+------+----------+

|    1 |       13 |

|    2 |        9 |

|    3 |       12 |

|    4 |        6 |

+------+----------+

4 rows in set (0.00 sec)

MySQL还支持使用GROUP BY进行显式排序(即通过对GROUP BY列使用显式ASC或DESC指示符)

mysql> SELECT id, SUM(cnt) FROM t GROUP BY id DESC;  --GROUP BY显式排序

+------+----------+

| id   | SUM(cnt) |

+------+----------+

|    4 |        6 |

|    3 |       12 |

|    2 |        9 |

|    1 |       13 |

+------+----------+

4 rows in set (0.00 sec)

从MySQL8.0开始,MySQL不再支持GROUP BY的隐式或显示排序,如下所示:

#下面实验环境为MySQL 8.0.18

mysql> select version();

+-----------+

| version() |

+-----------+

| 8.0.18    |

+-----------+

1 row in set (0.00 sec)

 

mysql> CREATE TABLE t (id INTEGER,  cnt INTEGER);

Query OK, 0 rows affected (0.39 sec)

 

mysql> INSERT INTO t VALUES (4,1),(3,2),(1,4),(2,2),(1,1),(1,5),(2,6),(2,1),(1,3),(3,4),(4,5),(3,6);

Query OK, 12 rows affected (0.10 sec)

Records: 12  Duplicates: 0  Warnings: 0

 

mysql> SELECT id, SUM(cnt) FROM t GROUP BY id;

+------+----------+

| id   | SUM(cnt) |

+------+----------+

|    4 |        6 |

|    3 |       12 |

|    1 |       13 |

|    2 |        9 |

+------+----------+

4 rows in set (0.00 sec)

 

mysql> SELECT id, SUM(cnt) FROM t GROUP BY id DESC;

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DESC' at line 1

如上所示,GROUP BY隐式排序不支持了,在MySQL 8.0中,上面测试例子是无序的。GROUP BY显示排序则直接报错。所以如果有数据库从MySQL 5.7或之前的版本,迁移升级到MySQL 8的话,就需要特别留意这个问题了。正确的做法应该是GROUP BY .. ORDER BY 这种操作。如下所示:

mysql>  SELECT id, SUM(cnt) FROM t GROUP BY id

    ->  ORDER BY id;

+------+----------+

| id   | SUM(cnt) |

+------+----------+

|    1 |       13 |

|    2 |        9 |

|    3 |       12 |

|    4 |        6 |

+------+----------+

4 rows in set (0.00 sec)

 

mysql> 

MySQL 8.0.13中删除了GROUP BY的显式排序。至于为什么MySQL 8.0不再支持GROUP BY的隐式排序和显示排序,这篇文章“Removal of implicit and explicit sorting for GROUP BY”已经有详细的介绍,这里不画蛇添足了。

参考资料:

https://mysqlserverteam.com/removal-of-implicit-and-explicit-sorting-for-group-by/

MySQL解惑——GROUP BY隐式排序的更多相关文章

  1. MySQL解惑——GROUP BY隐式排序

    原文:MySQL解惑--GROUP BY隐式排序 MySQL中GROUP BY隐式排序是什么概念呢? 主要是其它RDBMS没有这样的概念,如果没有认真了解过概念,对这个概念会感觉有点困惑,我们先来看看 ...

  2. mysql的几种隐式转化

    1. 表定义是字符型,传入的是Int 2. 字符集不一致.表定义的字段是gbk,传入的是utf8:这种在存储过程中出现得比较多. 数据库的字符集utf8 mysql> show create d ...

  3. MySQL索引失效之隐式转换

    常见索引失效: 1. 条件索引字段"不干净":函数操作.运算操作 2. 隐式类型转换:字符串转数值:其他类型转换 3. 隐式字符编码转换:按字符编码数据长度大的方向转换,避免数据截 ...

  4. MySQL隐式转化整理

    MySQL隐式转化整理 前几天在微博上看到一篇文章:价值百万的 MySQL 的隐式类型转换感觉写的很不错,再加上自己之前也对MySQL的隐式转化这边并不是很清楚,所以就顺势整理了一下.希望对大家有所帮 ...

  5. mysql的隐式转化

    MySQL隐式转化整理 前几天在微博上看到一篇文章:价值百万的 MySQL 的隐式类型转换感觉写的很不错,再加上自己之前也对MySQL的隐式转化这边并不是很清楚,所以就顺势整理了一下.希望对大家有所帮 ...

  6. MySQL的隐式类型转换整理总结

    当我们对不同类型的值进行比较的时候,为了使得这些数值「可比较」(也可以称为类型的兼容性),MySQL会做一些隐式转化(Implicit type conversion). 比如下面的例子:   1 2 ...

  7. MySQL SQL优化之字符串索引隐式转换

    之前有用户很不解:SQL语句非常简单,就是select * from test_1 where user_id=1 这种类型,而且user_id上已经建立索引了,怎么还是查询很慢? test_1的表结 ...

  8. Mysql隐式类型转换原则

    MySQL 的隐式类型转换原则: - 两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=> 对两个 NULL 做比较时会返回 1,这两种情况都不需要做类型转换 ...

  9. MYSQL中默认隐式事务及利用事务DML

    一:默认情况下,MySQL采用autocommit模式运行.这意味着,当您执行一个用于更新(修改)表的语句之后,MySQL立刻把更新存储到磁盘中.默认级别为不可重复读. 二:会造成隐式提交的语句以下语 ...

随机推荐

  1. kettle教程---kettle作业调度,附件(excel)配置表名,一个调度完成所有的表操作

    在平时工作当中,会遇到这种情况:复制一个库,几百甚至上千张表,并且无法设置dblink,此时通过kettle可以快速完成该任务. 按照正常的调度,有几百张表,咱们就要写几百个转换去处理,很不科学,下面 ...

  2. STM32调试总结

    1.卡死在这里的问题:没有中断处理函数,程序无法进入中断处理函数.DMA2_Channel3_IRQHandlerDMA2_Channel4_IRQHandlerDMA2_Channel5_IRQHa ...

  3. 联合查询和数据库设计e-r图

    联合查询: 联合查询的关键字是: union 基本含义 联合查询就是将两个select语句的查询结果“层叠”到一起成为一个“大结果”. 两个查询结果的能够进行“联合”的先觉条件是:结果字段数相等. 就 ...

  4. Weed3 for java 新的微型ORM框架

    Weed3,微型ORM框架(支持:java sql,xml sql,annotation sql:存储过程:事务:缓存:监听:等...) 05年时开发了第一代: 08年时开发了第二代,那时候进入互联网 ...

  5. C语言每日一练——第7题

    一.题目要求 已知数据文件in.dat中存有200个四位数,把这些数存到数组a中,编写函数jsVal(),其功能是:把千位数字和十位数字重新组成一个新的含有两位数字的数ab(新数的十位数字是原四位数的 ...

  6. 在 Windows 10 上搭建 Cordova 跨平台开发 Android 环境

    目录 安装 Cordova 安装 Java 和 Android 环境 创建 Cordova 应用程序 构建和运行 Cordova Cordova 简介:Cordova 原名 PhoneGap,是一个开 ...

  7. centos7 redis 6379端口telnet不通

    1.查看redis服务是否启动,如图所示,redis已经启动 2.查看是否监听正确的ip和端口 发现问题:端口号6379没错,但是ip是127.0.0.1,表示只能本地访问,问题就出在这. 3.修改r ...

  8. springboot-eureka交流机制

    一 前言 这篇文章参考了官方文档,主要是描述了eureka client 和 eureka server 之间的交流机制: peer to peer 的 对等复制交流机制: eureka 官方文档 二 ...

  9. 探索JAVA并发 - 可重入锁和不可重入锁

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...

  10. java正则表达式大全(常用)

    一.校验数字的表达式 数字:^[-]*$ n位的数字:^\d{n}$ 至少n位的数字:^\d{n,}$ m-n位的数字:^\d{m,n}$ 零和非零开头的数字:^(|[-][-]*)$ 非零开头的最多 ...