【mysql5.7】组内分组排序

介绍

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

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万数据的表
【mysql5.7】组内分组排序_第1张图片
表结构如下:

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 ;
    

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

你可能感兴趣的:(java,数据库,java,mysql)