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. 正则replace 回调函数里接收的参数是什么?

    前言 我们都知道 replace 在做替换处理方面会很常用,通常也是第一个会想到的方法.replace 第一个参数可以传入 string 或 RegExp,第二个参数可以传入 string 或 一个回 ...

  2. HTTP请求流程你了解了么?

    我又回来了,先来波推广,最硬的资源来自公众号:前端美食汇,欢迎大家关注公众号获取最新的技术.提示,文末有福利,最硬的文章会首先发布在公众号上喔 预备知识 前文没有描述到传输和协议直接的层级对应关系,大 ...

  3. 【CSS】352- 有趣的CSS弹跳动画

    点击上方"前端自习课"关注,学习起来~ 这是只用了一个div来做的小动画,纯粹利用CSS3的animation来完成,就像是一个正方形在地上弹跳,碰到地面的时候尖角还会压缩变圆,阴 ...

  4. python + selenium WebDriver的环境配置

    想试用python语言来学习selenium WebDriver,首先需要搭建一个测试环境,从python安装到浏览器插件配置的详细步骤,总结如下: 一.python环境配置 1.从官网下载最新的一个 ...

  5. CSS | 自适应两栏布局方法

    html代码: <div class="main"> <div class="left" style="background: #0 ...

  6. 《Java知识应用》Java Json说明和使用(fastjson)

    工具包下载:链接: https://pan.baidu.com/s/1dn5uNwiJ1ICkbPknlMmkHQ 提取码: ayzn 复制这段内容后打开百度网盘手机App,操作更方便哦 1.JSON ...

  7. 《Java基础知识》Java正则表达式

    正则表达式定义了字符串的模式. 正则表达式可以用来搜索.编辑或处理文本. 正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别. 正则表达式实例 一个字符串其实就是一个简单的正则表达式,例如  ...

  8. Object类和异常

    Object类(所有类的顶级父类) 今天说的两个方法: equals:         用于比较两个对象是否相同,它其实是使用两个对象的内存地址进行比较,底层默认使用的是==比较运算符来判断的.    ...

  9. 分享一篇关于C#大文件上传的整个过程

    简单写个小例子,记录一下此次大文件上传遇到的所有问题. 一.客户端(使用winform窗体实现) 具体功能: 点击“选择”按钮,选择要上传的文件 点击“上传文件”按钮,上传该文件调用UpLoad_Re ...

  10. 百万级高并发mongodb集群性能数十倍提升优化实践

    背景 线上某集群峰值TPS超过100万/秒左右(主要为写流量,读流量很低),峰值tps几乎已经到达集群上限,同时平均时延也超过100ms,随着读写流量的进一步增加,时延抖动严重影响业务可用性.该集群采 ...