美文网首页
获取group by最后一条记录

获取group by最后一条记录

作者: Gorgine | 来源:发表于2022-04-04 16:33 被阅读0次

    获取group by最后一条记录

    创建测试表

    create table login_log (id int primary key auto_increment, uid int, login_at datetime, login_device varchar(16))
    

    插入数据

    INSERT INTO `login_log` (`id`, `uid`, `login_at`, `login_device`) VALUES (1, 1, '2022-04-01 14:34:54', 'PC');
    INSERT INTO `login_log` (`id`, `uid`, `login_at`, `login_device`) VALUES (2, 2, '2022-03-01 14:35:08', 'MOBILE');
    INSERT INTO `login_log` (`id`, `uid`, `login_at`, `login_device`) VALUES (3, 1, '2022-04-14 14:35:27', 'WEB');
    INSERT INTO `login_log` (`id`, `uid`, `login_at`, `login_device`) VALUES (4, 2, '2022-04-30 14:35:35', 'WEB');
    

    查看数据

    select * from login_log;
    
    id  uid login_at            login_device
    1   1   2022-04-01 14:34:54 PC
    2   2   2022-03-01 14:35:08 MOBILE
    3   1   2022-04-14 14:35:27 WEB
    4   2   2022-04-30 14:35:35 WEB
    

    group by后默认是获取第一条记录的,

    如果只想获取group by后的某个字段的最大值,比如说要获取用户最后的登录时间,那么我们可以:

    select uid, max(login_at) as last_login_at from login_log group by uid
    
    uid last_login_at
    1   2022-04-14 14:35:27
    2   2022-04-30 14:35:35
    

    但是,我们可能会有这样的需求:获取用户的最后登录时间以及登录设备

    你可能会想到:

    select uid, max(login_at) as last_login_at, login_device from login_log group by uid
    

    这样是不行的,上面已经提及到group by后默认是会取第一条数据,所以这样查出来的login_device将会是分组后的第一条数据,即用户第一次登录时所使用的设备,而不是最后登录时间所对应的登录设备。

    那么有以下几种

    解决方案

    • 子查询的方式(可读性最好):
    select * from login_log where id in (select max(id) from login_log group by uid)
    

    or

    select * from login_log as log1 join (select max(id) as id from login_log group by uid) as log2 where log1.id = log2.id
    
    • 连表的方式
    select log1.* from login_log as log1
    left join login_log as log2 on log1.uid = log2.uid and log1.id < log2.id
    where log2.id is null
    
    • exists的方式
    select
    *
    from login_log as log1
    where not exists (
      select * from login_log as log2
      where log2.uid = log1.uid
      and log2.Id > log1.Id
    )
    
    • window function的方式(mysql8)
    WITH ranked_log AS (
      SELECT log.*, ROW_NUMBER() OVER (PARTITION BY uid ORDER BY id DESC) AS rn
      FROM login_log AS log
    )
    SELECT * FROM ranked_log WHERE rn = 1;
    

    参考文档:StackOverflow

    相关文章

      网友评论

          本文标题:获取group by最后一条记录

          本文链接:https://www.haomeiwen.com/subject/whbcsrtx.html