Mysql 查询分组数据中每组某一数值最大的数据
方法一、将时间进行排序后再分组
该表表名为customer, park_id表示园区id,joined_at表示用户的加入时间,created_at表示用户的创建时间。
需求:查出每个园区中,最早加入园区的第一位用户
select * from (select * from customer order by joined_at,created_at asc limit 1000) as tem group by park_id;
查出id为 1和9的两条数据
解题思路:
【提示】 此处使用 limit 是为了确保,group by分组的时候会按照子查询中输出的排列顺序进行分组。
group by 之后拿取的数据,是每个分组中的第一条数据。
所以我们只需要保证将joined_at时间最早的数据排在最前面,当以park_id进行分组操作时,拿到的第一条数据必然是joined_at时间最早的一条。
(数据重复时的处理)观察表我们可以看到id为1和12的数据都是2020-04-17加入的,但是两者之间他们的创建时间又有先后顺序的区分,id为12的要早一天,所以我们需要的是id为12的。 此刻我们就在排序的时候将created_at的排序加在joined_at后面。
这样就实现了在主要字段joined_at有重复数据的时候,我们按照第二个排序规则created_at字段进行追加排序,并拿取joined_at和created_at时间为最新的
方法二、拿取到每组最小时间并进行关联查询
需求:查询出每个园区最早加入的客户信息
select * from customer as c right join (select park_id,min(joined_at) as min_joined_at from customer group by park_id) as tem
on c.park_id=tem.park_id and c.joined_at=tem.min_joined_at;
查询结果:
根据查询可以看出,314园区的两条加入时间最早的数据都被查询了出来。
解题思路:
1. 子查询是按照park_id进行分组,并使用sql函数min 拿取到每组中加入时间最小的时间min_joined_at。并行程临时表tem
2. 根据拿取到的每个园区最小的加入时间关联查询,将其和customer表进行关联,按照park_id相等,且用户的加入时间于最小的加入时间min_joined_at相等来拿取对应的数据。
总结:由以上两个操作观察可知,
第一个方法更适合拿取按照条件进行分组后数据有重复,但我们仅取一条的需求。或者是有多个排序规则,我们按照多个排序规则进行处理后,拿取其中最匹配的一条。需要注意的一点是oracle并不支持该种方法
方法二更适合按条件分组后没有重复数据,或者有重复数据,且我们是要拿取所有符合条件的重复数据。