mysql关于group by分组取创建时间最新/某个值最大的记录 的讨论
1.数据表test的结构和数据如下:
问题:
1.我只想获取某个项目(project_id=1)的最新评论。(create_time越大,说明评论越新)
按道理可以这样做:
1)排好序 SELECT * FROM `test` where project_id = 1 order by project_id,create_time desc;
2)然后在上面排好序的基础上分组
select * from (SELECT * FROM `test` where project_id = 1 order by project_id,create_time desc) t GROUP BY project_id;
结果是看似正确的,实则是错误的。
如:修改id为1的create_time,然后再排序:
可以看到id为1的数组被排到最后。再对该结果进行分组:
select * from (SELECT * FROM `test` where project_id = 1 order by project_id,create_time desc) t GROUP BY project_id;
从结果可以看到,我们需要的数据是id为4的数据,但分组后却拿到了id为1的数据,这显然是错误的。
如果不限定project_id,对整个数据表进行排序:
SELECT * FROM `test` order by project_id,create_time desc;
然后对project_id分组:
select * from (SELECT * FROM `test` order by project_id,create_time desc) t GROUP BY project_id;
从分组后的结果可以看到:对于每一个分组,分组后的结果总是取组中主键(id)最小的数据,即group by project_id 总会对project_id执行排序(正序)
而不论临时表(t)中的project_id是否已排序,然后取组中主键id最小(如id为1)的一行数据。换句话说 临时表t 内的排序 无法影响外层的group by 的操作。
通过上面的实验可知 select * from (SELECT * FROM `test` order by project_id,create_time desc) t GROUP BY project_id; 无法获取项目的最新评论
可以通过以下方法获取项目的最新评论:
(1)
SELECT t.* FROM test t JOIN ( SELECT SUBSTRING_INDEX( group_concat( id ORDER BY create_time DESC ), ',', 1 ) AS id FROM test GROUP BY project_id ) tmp ON t.id = tmp.id;
其结果为:
分析结果可知,此为正确结果。
注:group_concat 用法 (默认连接符为',')
select group_concat(project_id,'-',create_time,'-',status order by create_time desc SEPARATOR ',') as info from test GROUP BY project_id;
SUBSTRING_INDEX 用法:下面的例子取排序好的分组的第一条数据