MYSQL5.7特性之GROUP BY 排序

Posted 炉门点饭

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MYSQL5.7特性之GROUP BY 排序相关的知识,希望对你有一定的参考价值。

背景

最近某同事问我一个关于group by 后需要返回每个分类最新/最老的创建时间的数据,随后我想了想...叮,还好记得以前有遇到过这样的疑问,就给他说使用子查询就好了。。如果事情这么简单。。就没有这篇东西了。

分析

原来的语句

select * from tb_test where tt_id = 9000 GROUP BY tt_id order by create_time desc;

我们改了之后还有问题的语句

select * from (select * from tb_test where tt_id = 9000 order by create_time desc) as sub GROUP BY tt_id;

上面条语句还是不能进行排序后分组的

于是想起来应该还是要加些什么东西的,搜索了以前的记录发现有关于5.7的 derived_merge(派生合并) 优化

可以通过下面几个关键字阻止合并操作

DISTINCT
GROUP BY
HAVING
LIMIT

于是就有了

select * from (select * from tb_test where tt_id = 9000 having 1=1 order by create_time desc) as sub GROUP BY tt_id;

就是增加一个 having关键字,当然你的语句如果正好有其他关键字那么是不用再增加了,我们原来打算增加limit但是这感觉太挫了。。。

有一个方法可以看到是否进行了

执行 explain,可以看到下面的话就没有进行derived_merge ,否则就是执行了
2   DERIVED   tb_test   ALL    49 10.00   Using where; Using filesort

derived_merge 拓展

derived_merge 是5.7版本做的一个优化吧,所以去除派生类与外部块合并,是可以减少查询开销,派生类是个临时表,开辟一个临时表的同时还要维护和排序或者分组,都会影响效率。

多种办法不需要修改 derived_merge 参数而使合并派生类失效,原文如下

可以通过在子查询中使用任何阻止合并的构造来禁用合并,尽管这些构造对实现的影响并不明确。防止合并的构造对于派生表和视图引用是相同的:1.聚合函数( SUM() , MIN() , MAX() , COUNT()等)2.DISTINCT3.GROUP BY4.HAVING5.LIMIT6.UNION或UNION ALL7.选择列表中的子查询8.分配给用户变量9.仅引用文字值(在这种情况下,没有基础表)

因为mysql 这个优化会导致我们的子查询语句会合并在一起和外部语句进行查询。


以上是关于MYSQL5.7特性之GROUP BY 排序的主要内容,如果未能解决你的问题,请参考以下文章

MySQL5.7之group by语法问题

mysql5.7升级问题GROUP BY不兼容sql_mode=only_full_group_by

MYsql5.7版本之后,用group by查询不在分组字段遇到的坑

Mysql5.7以上版本group by报错问题

mysql5.7 group by语法 1055

MYSQL5.7 sql_mode=only_full_group_by