sql中实现先排序后分组
数据表结构和数据如下:
CREATE TABLE `commun_message_chat_single` (
`id` int() NOT NULL AUTO_INCREMENT,
`chat_id` int() DEFAULT '' COMMENT '会话id',
`from_id` varchar() DEFAULT NULL COMMENT '发送者 用户id',
`to_id` varchar() DEFAULT NULL COMMENT '接收者 用户id',
`content` text COMMENT '消息内容',
`type` tinyint() DEFAULT '' COMMENT '消息类型 1:文字 2:图片 3:文件',
`send_time` datetime DEFAULT NULL COMMENT '消息发送时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='单聊 聊天记录'; -- 插入数据的sql
INSERT INTO `commun_message_chat_single` VALUES (, , '', 'md_1', '', , '2019-10-16 08:25:50');
INSERT INTO `commun_message_chat_single` VALUES (, , '', 'md_1', '', , '2019-10-28 08:25:59');
INSERT INTO `commun_message_chat_single` VALUES (, , '', 'md_2', '', , '2019-10-01 08:26:21');
INSERT INTO `commun_message_chat_single` VALUES (, , '', 'md_2', '哈哈哈', , '2019-10-27 08:26:34');
INSERT INTO `commun_message_chat_single` VALUES (, , '', 'md_2', '测试测试', , '2019-10-10 08:28:27');
目前数据表所有数据如下:
mysql> select * from commun_message_chat_single where from_id = '11';
+----+---------+---------+-------+--------------+------+---------------------+
| id | chat_id | from_id | to_id | content | type | send_time |
+----+---------+---------+-------+--------------+------+---------------------+
| 60 | 10 | 11 | md_1 | 123 | 1 | 2019-10-16 08:25:50 |
| 61 | 10 | 11 | md_1 | 456 | 1 | 2019-10-28 08:25:59 |
| 62 | 10 | 11 | md_2 | 789 | 1 | 2019-10-01 08:26:21 |
| 63 | 10 | 11 | md_2 | 哈哈哈 | 1 | 2019-10-27 08:26:34 |
| 64 | 10 | 11 | md_2 | 测试测试 | 1 | 2019-10-10 08:28:27 |
+----+---------+---------+-------+--------------+------+---------------------+
5 rows in set (0.00 sec)
需求:查询from_id为11的数据 并且 和 每一个to_id 按照时间排序显示最新的一条数据(也就是显示:to_id是md_1的,按照时间排序id为61的符合结果;to_id是md_2的,按照时间排序id为63的符合结果)
符合该需求的2条数据如下:
+----+---------+---------+-------+-----------+------+---------------------+
| id | chat_id | from_id | to_id | content | type | send_time |
+----+---------+---------+-------+-----------+------+---------------------+
| 61 | 10 | 11 | md_1 | 456 | 1 | 2019-10-28 08:25:59 |
| 63 | 10 | 11 | md_2 | 哈哈哈 | 1 | 2019-10-27 08:26:34 |
+----+---------+---------+-------+-----------+------+---------------------+
实现该需求的sql语句如下(利用sql中的子查询):
SELECT * FROM (SELECT * FROM commun_message_chat_single WHERE from_id = '11' ORDER BY send_time DESC ) as
temp_table GROUP BY temp_table.to_id; -- 大概解释下该条sql语句:括号内的子查询是查询from_id为11的数据并且按照send_time从高到低排序,这里的子查询的结果会生成一个临时表,临时表这里取名为temp_table,然后外部查询将temp_table的结果进行分组。
mysql5.7版本以下执行结果如下(只在5.5和5.6版本试过):
+----+---------+---------+-------+-----------+------+---------------------+
| id | chat_id | from_id | to_id | content | type | send_time |
+----+---------+---------+-------+-----------+------+---------------------+
| 61 | 10 | 11 | md_1 | 456 | 1 | 2019-10-28 08:25:59 |
| 63 | 10 | 11 | md_2 | 哈哈哈 | 1 | 2019-10-27 08:26:34 |
+----+---------+---------+-------+-----------+------+---------------------+
2 rows in set (0.00 sec)
mysql5.7版本执行结果如下:
+----+---------+---------+-------+---------+------+---------------------+
| id | chat_id | from_id | to_id | content | type | send_time |
+----+---------+---------+-------+---------+------+---------------------+
| | | | md_1 | | | -- :: |
| | | | md_2 | | | -- :: |
+----+---------+---------+-------+---------+------+---------------------+
rows in set (0.00 sec)
what?为啥5.7以下的版本是我们想要的结果,而5.7版本的执行结果居然不是我们期待的结果!高版本居然执行的结果不正确。。
为什么mysql5.7和5.7以下的版本会有不同的结果呢?
可以分别查看一下这条sql语句在两个不同版本数据库的sql执行计划:
mysql 5.7.21:
mysql5.5.62和5.6.44:
对比可以发现5.7版本的mysql在执行这条sql语句的时候缺少了一个derived的操作,通过查阅相关资料了解到mysql5.7对子查询进行了优化,认为子查询中的order by可以进行忽略,只要Derived table里不包含如下条件就可以进行优化:
①、UNION clause
②、GROUP BY
③、DISTINCT
④、Aggregation
⑤、LIMIT or OFFSET
看到了吧,如果要在mysql5.7中实现先排序后分组,这里可以加个limit,不过你的limit要足够大
mysql5.7解决办法如下:
SELECT * FROM (SELECT * FROM commun_message_chat_single WHERE from_id = '' ORDER BY send_time DESC LIMIT
) as temp_table GROUP BY temp_table.to_id;
mysql8.0及以上版本没试过,不过应该和5.7是一样的效果,都进行了优化。
PS:子查询不是mysql独有的,sqlserver等数据库也可以使用子查询
sql中实现先排序后分组的更多相关文章
- MySql下实现先排序后分组
最近在工作中遇到一个先排序后分组的需求,发现MySql不同的版本有不同的结果,特此记录. 举例:要求在shop表中查询出各类型商店中价格最高的商品. --表结构-- create table `sho ...
- Java基础知识强化之IO流笔记52:IO流练习之 把一个文件中的字符串排序后再写入另一个文件案例
1. 把一个文件中的字符串排序后再写入另一个文件 已知s.txt文件中有这样的一个字符串:"hcexfgijkamdnoqrzstuvwybpl" 请编写程序读取数据内容,把数据排 ...
- SQL中条件放在on后与where后的区别
SQL中on条件与where条件的区别 数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户. 在使用left jion时,on和where条件的区别如下: ...
- SQL中前置0和后置0的处理问题
在sql语句中经常遇到处理前置和后置数据的问题 1.首先使用convert转化函数对预处理的数据进行转化,CONVERT()函数可以将制定的数据类型转换为另一种数据类型 MySQL 的CAST()和C ...
- sql中的group by 和 having 用法解析
转载博客:http://www.cnblogs.com/wang-123/archive/2012/01/05/2312676.html --sql中的group by 用法解析:-- Group B ...
- sql中group by 和having 用法解析
--sql中的group by 用法解析:-- Group By语句从英文的字面意义上理解就是“根据(by)一定的规则进行分组(Group)”.--它的作用是通过一定的规则将一个数据集划分成若干个小的 ...
- mysql 怎样先排序再分组
权游游牧族:众所周知!一句SqL语句不能先排序再分组.所以这里给出几个案例 --表结构-- create table `shop` ( `id` int (10) PRIMARY KEY, `shop ...
- 在oracle中,group by后将字符拼接,以及自定义排序
1.在oracle中,group by后将字符拼接.任务:在学生表中,有studentid和subject两个字段.要求对studentid进行group by分组,并将所选科目拼接在一起.oracl ...
- mssql sqlserver 使用sql脚本获取群组后,按时间排序(asc)第一条数据的方法分享
摘要: 下文讲述使用sql脚本,获取群组后记录的第一条数据业务场景说明: 学校教务处要求统计: 每次作业,最早提交的学生名单下文通过举例的方式,记录此次脚本编写方法,方便以后备查,如下所示: 实现思路 ...
随机推荐
- Quartz系列(一):基础介绍
新建一个.NET Core控制台项目,NuGet引用Quartz引用. class Program { static void Main(string[] args) { var task = Tas ...
- jquery 全选,反选
<?php foreach ($contents as $item) { ?> <tr> <td><input name="qx" val ...
- jQuery查找节点(选择器)
jQuery通过选择器来完成节点的查找: 1.基本选择器: ①通用/所有的选择器:$("*") //使用*号来表示. ②:标签选择器:$("标签名(div)") ...
- BootstrapVue 安装指南
BootstrapVue 是基于 Bootstrap v4 + Vue.js 的前端 UI 框架.BootstrapVue 作为学习 Vue.js 框架本身的入门框架,我认为是非常不错的.Bootst ...
- Spring Cloud Config Server 节点迁移引起的问题,请格外注意这一点!
前言: 虽然强烈推荐选择使用国内开源的配置中心,如携程开源的 Apollo 配置中心.阿里开源的 Nacos 注册&配置中心. 但实际架构选型时,根据实际项目规模.业务复杂性等因素,有的项目还 ...
- 教你如何判断URL的好坏
1.最核心-网站整体内容质量2.关键词整理拓展及关键词布局3.网站外部链接建设4.网站内链建设合理5.面包屑导航6.友情链接7.404页面网站的SEO站外优化+SEO外链建设 层级:三层为好,301重 ...
- 二次函数,为什么a>0就可以知道开口向上.
最近自考. 学习高等数学. 学习高等数学过程中发现高中数学不会,,于是乎开始补高中数学. 学习高中数学过程中又发现初中数学有的不会,,于是乎开始补初中数学.. 可怕(→_→). 今天遇到一个二次函数, ...
- 流水线机制、滑动窗口协议、GBN、SR
一.滑动窗口协议 为了解决停等操作的性能问题(发了一个分组之后一直等到确认了这个分组才发下一个),推出了流水线机制,提供资源利用率.就是允许发送方在收到对方的ACK前,发送多个分组 其中窗口是一个范围 ...
- Python的字符串编码
本文用实验详细地演示了Python2和Python3在字符串编码上的区别. 在Python2中,字符串字面量对应于8位的字符或面向字节编码的字节字面量.这些字符串的一个重要限制是它们无法完全地支持国际 ...
- 从实践角度重新理解BIO和NIO
前言 这段时间自己在看一些Java中BIO和NIO之类的东西,看了很多博客,发现各种关于NIO的概念说的天花乱坠头头是道,可以说是非常的完整,但是整个看下来之后,自己对NIO还是一知半解的状态,所以这 ...