获取使用group by 分组后的组内最新(最大,最...)的一条数数据

sql取group by 分组后的组内最新(最大,最…)的一条数数据

最近一个有个需求是 , 取分组后的组内最新的一条数据, 正常来说写法如下

select a.* from
	(
	select cluesTaracking_id,cluesId,trackingTime,fail_why from cluestracking
	order by trackingTime desc
	) a
	group by a.cluesId

但是查询结果却是取得id最小的一条数据
不分组查询结果
在这里插入图片描述

分组后的查询结果
在这里插入图片描述

明显可以看出分组后并没有取trackingTime最大的一条数据

解决方案

方法一

在order by后面添加 limit X, 比如这里添加limit 100, sql如下

select a.* from
	(
	select cluesTaracking_id,cluesId,trackingTime,fail_why from cluestracking
	order by trackingTime desc
	limit 100
	) a
	group by a.cluesId

查询结果如下
在这里插入图片描述

可以看到, 已经将分组后组内最新的一条数据查出

问题解析:

通过explain方式, 查看执行逻辑
将limit 100注释掉
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iEEd1000-1608015395467)(en-resource://database/515:0)]

发现这里的select_type是SIMPLE, SIMPLE表示这是一个
简单的SELECT语句(不包括UNION操作或子查询操作),
也就是虽然写了子查询和排序, 但是并未生效, 依然使用的是默认的排序, 即按照id升序排列

打开limit 100的注释

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nm6bjULq-1608015395469)(en-resource://database/517:0)]

PRIMARY
查询中最外层的SELECT(如两表做UNION或者存在子查询的外层的表操作为PRIMARY,内层的操作为UNION)
'DERIVED:
DERIVED表示被驱动的SELECT子查询(子查询位于FROM子句)
由此可见 , 在mysql 5.7中, 如果想要获取分组后的最新数据, 必须加上limit 条数, 这里可以指定一个不可能查询出的数值,如1000等

方法二 使用 MAX() 聚合函数

 select cluesTaracking_id,cluesId,
 MAX(trackingTime),
 fail_why from cluestracking
	group by cluesId
	order by trackingTime desc

查询结果如下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ldeDM001-1608015395472)(en-resource://database/519:0)]

方法一的查询结果如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y7oTkcgm-1608015395475)(en-resource://database/521:0)]

可以看到, 查询结果一致

在SQL中,有多种方法可以在使用`GROUP BY`分组后显示内第一条记录。 ### 使用`ROW_NUMBER()`函 `ROW_NUMBER() OVER (PARTITION BY COL1 ORDER BY COL2)`可以根据`COL1`分组,在分组内部根据`COL2`排序,此函计算的值表示每内部排序后的顺序编号(内连续且唯一)。可以筛选出编号为1的记录,即每的第一条记录。示例如下: ```sql -- 假设表名为table_name,分组字段为group_column,排序字段为sort_column SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY group_column ORDER BY sort_column) as rn FROM table_name ) subquery WHERE rn = 1; ``` 这里先使用`ROW_NUMBER()`函为每记录编号,然后在外部查询中筛选出编号为1的记录,也就是每的第一条记录。此方法适用于支持`ROW_NUMBER()`函数据库,如MySQL 8.0及以上版本、SQL Server等[^3]。 ### 使用`SUBSTRING_INDEX`和`GROUP_CONCAT`函(以MySQL为例) 以`id`为数据唯一键,`storage_time`为时间戳,`application_matters`为分组依据,示例如下: ```sql SELECT * FROM csrc_approved_products_weekly WHERE id IN ( SELECT SUBSTRING_INDEX(group_concat( id ORDER BY `storage_time` DESC ), ',', 1 ) FROM csrc_approved_products_weekly GROUP BY application_matters ); ``` 该方法先使用`GROUP_CONCAT`函将每内的`id`按照`storage_time`降序连接成一个字符串,然后使用`SUBSTRING_INDEX`函该字符串的第一个`id`,后通过`IN`子句筛选出对应记录[^5]。 ### 直接使用聚合函获取特定字段的第一条记录 可以使用分组和汇总函得到每个里的一个值(最大值小值等),但这种方法只能获取特定字段的值,不能获取整行数据。示例如下: ```sql SELECT 课程号,max(成绩) as 最大成绩 from score group by 课程号; ``` 这里通过`GROUP BY`对`课程号`分组使用`MAX`函获取`成绩`的最大值,但无法得到成绩最大值所在行的完整数据[^2]。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

意田天

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

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

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

打赏作者

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

抵扣说明:

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

余额充值