在实际的开发中,经常会遇到需要对 MySQL 查询结果按照某个字段进行分组,并按照另一个字段进行排序,并且只取每组的第一条数据的需求。
比如在深入洽谈模块,需要根据项目、品牌分组,并且取每组中最新的一条数据。
分析:按照项目、品牌分组之后,还需要按创建时间降序排序,取第一条数据。
1、查询表数据
首先,我们需要从数据库中查询出需要处理的数据。
select
project_id, brand_name,
id, discuss_no, discuss_status, created_time
from
lea_discuss
2、按字段分组
接下来,我们需要按照某个字段进行分组。假设我们要按照 project_id, brand_name 字段进行分组。
使用 GROUP BY 关键字来实现分组:
select
project_id, brand_name,
id, discuss_no, discuss_status, created_time
from
lea_discuss
group by project_id,brand_name
这条 SQL 语句会将查询结果按照 project_id, brand_name 字段进行分组,每个分组只返回一条数据。
3、按字段排序
在分组的基础上,我们可能还需要按照另一个字段进行排序。假设我们要按照 created_time 字段进行降序排序。
使用 ORDER BY 关键字来实现排序:
select
project_id, brand_name,
id, discuss_no, discuss_status, created_time
from
lea_discuss
group by project_id,brand_name
order by created_time desc
这条 SQL 语句会将分组后的结果按照 created_time字段进行降序排序。
4、取每组第一条数据
最后,我们只需要取每个分组的第一条数据即可。MySQL 提供了一个函数 GROUP_CONCAT 可以用来实现这个功能。
使用以下代码来取每组第一条数据:
select
project_id, brand_name,
SUBSTRING_INDEX(GROUP_CONCAT( distinct id order by created_time desc), ',', 1) id,
SUBSTRING_INDEX(GROUP_CONCAT( distinct discuss_no order by created_time desc), ',', 1) discuss_no,
SUBSTRING_INDEX(GROUP_CONCAT( distinct discuss_status order by created_time desc), ',', 1) discuss_status,
SUBSTRING_INDEX(GROUP_CONCAT( distinct created_time order by created_time desc), ',', 1) created_time
from
lea_discuss
group by project_id,brand_name
order by created_time desc
这条 SQL 语句通过 GROUP_CONCAT 函数将每个分组的 id 字段连接起来,并按照 created_time 字段降序排序。然后使用 SUBSTRING_INDEX 函数取连接后的字符串的第一部分作为最终结果。
但这个功能不能直接拿到最新的一条数据,而是对每个字段,进行排序然后拿到每个字段的最新的数据,如果字段过多那将非常麻烦。
select
*
from
(
select
SUBSTRING_INDEX(GROUP_CONCAT( distinct id order by created_time desc), ',', 1) idMax
from
lea_discuss
group by project_id,brand_name
) a
left join lea_discuss ld on a.idMax = ld.id
order by created_time desc
我们先根据上面的方法拿到排序之后每条数据的id,然后作为一张新表关联原来的表,这个时候就可以去到每组数据最新的值。