MySQL分组需求探秘

Posted bisal

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL分组需求探秘相关的知识,希望对你有一定的参考价值。

前两天同事有个mysql数据分组的需求,如下测试数据,需要找出每个name分组中create_date最近的记录,

需要注意的是,此处用的MySQL是5.6,最初是使用这条语句,

select name, value, create_date, update_date from t1 group by name order by create_date desc;

查询结果如下,看着好像是对的,但是仔细看下,就会发现其中的问题,例如name=a最近的create_date应该是value=3的记录,name=d最近的create_date应该是value=10的记录,

用这条SQL得到的其实只是每个name分组中最先插入的记录,然后按照create_date进行了降序排列,和原始需求,完全不同。

此时可采用分而治之的策略,先做排序,再做分组,

select * from (select name, value, create_date, update_date from t1 order by create_date desc) t group by t.name;

即可得到原始需求的数据,

当然,针对此需求,可能有其他方法,有兴趣的朋友,可以尝试写写,共享一下。

可能有细心的朋友会发现个问题,就是上述SQL中的group by,好像有些奇怪,如果按照常规,select中的字段需要出现在group by中,上述语句竟然没报错?

如果我们在MySQL 5.7执行相同的语句,

select name, value, create_date, update_date from t1 group by name order by create_date desc; 

就会提示这个错,

如果是在Oracle,则会提示这个,

难道这是MySQL 5.6的特性?搜了一下,其实因为这个,在这套5.6的环境中,sql_mode参数如下,

而在5.7中,sql_mode参数如下,多了一个ONLY_FULL_GROUP_BY,他的意思是“出现在SELECT语句、HAVING条件和ORDER BY语句中的列,必须是GROUP BY的列或者依赖于GROUP BY列的函数列”,这就不难解释,为什么5.6和5.7中现象是不同的,还是因为5.7默认对SQL格式校验的要求高了,

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

因此从5.6升级到5.7,很可能出现这种相同的SQL执行结果不同的现象,这对兼容性测试的要求就会很高,究其原因,一方面是特性决定的,另一方面就是各种配置参数不同导致的。

可以在5.7的sql_mode中删除这个ONLY_FULL_GROUP_BY,即可达到5.6相同效果了,或者改写SQL,例如,

select * from t1 a where create_date = (select max(create_date) from t1 b where a.name = b.name);

或者,

select * from t1 a where not exists (select * from t1 b where a.name = b.name and b.create_date > a.create_date);

MySQL 8.0支持row_number()函数,操作应该和如下Oracle相近的。

Oracle中可以使用row_number()实现此需求,

select * from (select name, create_date, row_number() over (partition by name order by create_date desc) as r from t1) where r=1;

近期更新的文章:

国产数据库排行榜解读

深度解读中国各大银行分布式数据库、数仓、数据中台、AIOps的落地与实践丨DAMS峰会

了解一下ISO 8601是什么

Linux系统中的kill -9和-15有什么区别?

小白学习MySQL - 查询会锁表?

文章分类和索引:

公众号700篇文章分类和索引

以上是关于MySQL分组需求探秘的主要内容,如果未能解决你的问题,请参考以下文章

MySQL InnoDB 存储引擎探秘

深度探秘 Java 8 函数式编程(上)

探秘SpringAop_介绍以及使用详解

MySQL的一个分组需求

MySQL的一个分组需求

php设计模式探秘-封装