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 用法:下面的例子取排序好的分组的第一条数据

      

 

posted @ 2021-04-01 19:02  不知起什么名字  阅读(4196)  评论(1编辑  收藏  举报