【mysql5.7】组内分组排序

本文介绍了如何利用SQL中的SUBSTRING_INDEX和GROUP_CONCAT函数来高效地查询每个设备的最新数据,对比了传统方法,展示了一种更快速的查询策略。在13万数据的表中,新方法的查询时间仅为0.682秒,比传统方法快了一倍。这种方法适用于处理大量数据时获取分组内的最新记录。
摘要由CSDN通过智能技术生成

介绍

一般地, 组内排序取最新数据时,会采用类似这样的写法:

select * from table1 as pmh,
          ( SELECT ponding_id,MAX(create_time) create_time
                 FROM table1  GROUP BY ponding_id ) as t1
    where t1.ponding_id = pmh.ponding_id and pmh.create_time = t1.create_time;

这里呢 ,我要介绍另一种方法:

SUBSTRING_INDEX( GROUP_CONCAT( 唯一字段1 ORDER BY 排序字段2 DESC ), ',',(取第几个) )

举例:

有一个这样的表:

CREATE TABLE `wisdom_well_cover` (
  `id` varchar(36) NOT NULL COMMENT '主键',
  `device_id` varchar(32) DEFAULT NULL COMMENT '设备编号',
  `device_type` varchar(32) DEFAULT NULL COMMENT '设备类型',
  `timestamp` datetime DEFAULT NULL COMMENT '接收时间'
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

需求:

查找每个设备的最新数据

select wwc.* from wisdom_well_cover wwc inner join (
	SELECT SUBSTRING_INDEX ( 
		GROUP_CONCAT( id ORDER BY TIMESTAMP DESC ), ',', 1 
	) AS id 
	FROM wisdom_well_cover GROUP BY device_id
) as t1 on wwc.id = t1.id

查找每个设备第二新的数据

select wwc.* from wisdom_well_cover wwc inner join (
	SELECT SUBSTRING_INDEX (
		SUBSTRING_INDEX ( 
			GROUP_CONCAT( id ORDER BY TIMESTAMP DESC ), ',', 2 
			),',',-1) AS id 
	FROM wisdom_well_cover GROUP BY device_id
) as t1 on wwc.id = t1.id
  1. SUBSTRING_INDEX 字符串截取
  2. GROUP_CONCAT 这个比较奇特 , 可以对分组连接后的字段进行排序,去重等等,
    具体可以自行学习. 连接后的各个字符串是用逗号分割的, 所以用到了字符串截取.

性能对比

这里有一张13万数据的表
在这里插入图片描述
表结构如下:

CREATE TABLE `ponding_model_history` (
  `id` varchar(36) NOT NULL,
  `create_by` varchar(50) DEFAULT NULL COMMENT '创建人',
  `create_time` datetime DEFAULT NULL COMMENT '创建日期',
  `acquisition_time` datetime DEFAULT NULL COMMENT '采集时间',
  ....此处省略其他字段....
  PRIMARY KEY (`id`) USING BTREE,
  KEY `acquisition_time_index` (`acquisition_time`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

用两种方法进行分组排序

  • 第一种 : 用时: 1.349s

    select * from ponding_model_history as pmh,
          ( SELECT ponding_id,MAX(create_time) create_time
                 FROM ponding_model_history 
                 GROUP BY ponding_id ) as t1
    where t1.ponding_id = pmh.ponding_id and pmh.create_time = t1.create_time;
    
  • 第二种 用时: 0.682s

    select * from ponding_model_history as pmh INNER JOIN 
          ( SELECT SUBSTRING_INDEX( GROUP_CONCAT( id ORDER BY create_time DESC ), ',', 1 ) id
                FROM ponding_model_history 
                GROUP BY ponding_id ) as t1
    on t1.id = pmh.id ;
    

经过验证 结果两种方法结果都无误

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qlanto

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值