我的编程空间,编程开发者的网络收藏夹
学习永远不晚

mysql中group by分组查询中查询最新字段值的sql语句怎么写?

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

mysql中group by分组查询中查询最新字段值的sql语句怎么写?

目录

背景

今天看代码的时候,看到一个比较复杂的sql语句,我知道这条sql语句最终想要实现的结果,所以我就想自己写sql来实现一下,看看速度会不会更好,然后发现别人的sql写法执行效率更高,由此打开了一个新的世界。

需求

在聊天消息记录表中查询该用户和其他消息发送者的“最近一条未读消息id、最近一条未读消息内容、最近一条未读消息接收时间、未读消息数量、消息发送者id、消息发送者名称”。其中表名是msg_record,相关字段如下:

列名解释
id消息记录id
toId消息接收者id
fromId消息发送者id
fromUsername消息发送者名称
date消息发送日期
hasRead是否已读
msgText消息内容

效率不高的sql写法

需求分析:

需要查询的结果中包含“最近一条未读消息id、最近一条未读消息内容、最近一条未读消息接收时间”,针对“最近一条未读消息接收时间”来说,可以使用聚合函数max(),但是剩余两个都是文本性质的内容,那就只能通过排序获取,针对Mysql数据库来说,如果我们获取非分组字段,那Mysql数据库会把分组中的第一条返回,所以利用这个特性,我们就先执行排序,然后在分组,之后利用Mysql的上述特性完成数据的获取工作

sql语句:

SELECTa.id,a.fromId,a.fromUsername,a.date,a.msgText lastMsg,count( a.id ) unReadCountFROM(-- 子查询SELECTid,fromId,fromUserName,date,msgText FROMmsg_recordWHEREfromId != "4ebd6f3485f140888ecc25c12e5105b1" AND toId = "4ebd6f3485f140888ecc25c12e5105b1" AND hasRead = FALSE ORDER BYdate DESC ) a GROUP BYa.fromId

执行分析:

在上述sql前面添加EXPLAIN字段即可,我们看下分析结果:

idselect_typetabletypepossible_keyskeykey_lenrefrowsExtra
1PRIMARYALL7Using temporary; Using filesort
2DERIVEDimq_server_messagerecordALLIDX_IMQ_SERVER_MESSAGERECORD_TOID,IDX_IMQ_SERVER_MESSAGERECORD_FROMIDIDX_IMQ_SERVER_MESSAGERECORD_TOID403117Using where; Using filesort

上述第二行代表子查询使用的是全表扫描,但是使用到了索引;第一行代表全表扫描,但是没有使用索引,两个都是全表扫描,说明效率是真的不高

经测试发现,执行时间大致是0.024秒左右

效率高的sql写法

需求分析:

既然先排序的方式不行,那我们就采用先分组在排序的方式来得到最终结果,这就需要使用到SUBSTRING_INDEX、GROUP_CONCAT、CONCAT函数,我们来解释一下这几个函数的含义:

  • SUBSTRING_INDEX:字符串切分函数
  • GROUP_CONCAT:字符串分组连接函数
  • CONCAT:字符串连接函数

详细分析可看:mysql取出每个分组中最新的记录(坑点勿踩)

sql语句:

SELECTSUBSTRING_INDEX( GROUP_CONCAT( CONCAT( id, '*splits*,' ) ORDER BY date DESC ), '*splits*,', 1 ) id,fromId,fromUsername,max( date ) date,SUBSTRING_INDEX( GROUP_CONCAT( CONCAT( msgText, '*splits*,' ) ORDER BY date DESC ), '*splits*,', 1 ) lastMsg,count( id ) unReadCount FROMmsg_recordWHEREtoId = "4ebd6f3485f140888ecc25c12e5105b1" AND fromId != "4ebd6f3485f140888ecc25c12e5105b1" AND hasRead = FALSE GROUP BYfromId

执行分析:

在上述sql前面添加EXPLAIN字段即可,我们看下分析结果:

idselect_typetabletypepossible_keyskeykey_lenrefrowsExtra
1SIMPLEIMQ_SERVER_MESSAGERECORDrefIDX_IMQ_SERVER_MESSAGERECORD_TOID,IDX_IMQ_SERVER_MESSAGERECORD_FROMIDIDX_IMQ_SERVER_MESSAGERECORD_TOID403const51Using where; Using filesort

可以看到使用的是ref扫描,并且使用到了索引,并且是常量类型的索引,这肯定速度就比较快。

经测试发现,执行时间大致是0.015秒左右

我们对上面那几个函数的使用情况进行一个解释,我们先使用CONCAT()函数对属性id进行字符串拼接,然后使用GROUP_CONCAT()按照时间进行排序之后在进行字符串拼接,这样就是一个很大的字符串了,之后在使用SUBSTRING_INDEX()进行按照分隔符进行数据截取,就可以获取到结果了

但是这种处理方式也有一个弊端,如果数据量很大的话,通过这几个函数执行相关操作,那就可能会出现内存泄露的问题,但是大部分情况还好

拓展

来源地址:https://blog.csdn.net/qq_42449963/article/details/131141375

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

mysql中group by分组查询中查询最新字段值的sql语句怎么写?

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

SQL怎么查询每个分组都出现的字段值

今天给大家介绍一下SQL怎么查询每个分组都出现的字段值。文章的内容小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着小编的思路一起来阅读吧。数据分组以后,要找出在每个分组中都出现的某个字段值。用SQ
2023-06-03

PGSQL怎么查询最近N天的数据及SQL语句实现替换字段内容的方法

这篇“PGSQL怎么查询最近N天的数据及SQL语句实现替换字段内容的方法”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“PGS
2023-03-09

编程热搜

目录