You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

技术求助:编写SQL查询获取每日用户最新签到记录(同一用户当日仅保留最新)

解决方案:获取每日用户最新签到记录

这个需求很常见,咱们可以用窗口函数或者关联子查询来实现,下面分别给出两种常用方案,你可以根据自己使用的数据库版本选择。

方案一:使用ROW_NUMBER()窗口函数(推荐)

这是最直观且高效的方法,适用于支持窗口函数的数据库(如MySQL 8.0+、PostgreSQL、SQL Server等)。

代码实现

SELECT 
    CAST(checkin_datetime AS DATE) AS date,
    user_id,
    office_id
FROM (
    SELECT 
        *,
        -- 按用户+日期分组,每组内按签到时间倒序编号
        ROW_NUMBER() OVER (
            PARTITION BY user_id, CAST(checkin_datetime AS DATE) 
            ORDER BY checkin_datetime DESC
        ) AS rn
    FROM CHECKIN_TABLE
) t
-- 只取每组的第一条(即最新的签到记录)
WHERE rn = 1
-- 按日期和用户ID排序,让结果更规整
ORDER BY date, user_id;

逻辑说明

  1. 内层子查询中,PARTITION BY user_id, CAST(checkin_datetime AS DATE) 会把数据按「用户ID+签到日期」分成多个独立的组;
  2. ORDER BY checkin_datetime DESC 让每个组内的记录按签到时间从晚到早排序,最新的记录会被标记为rn=1;
  3. 外层查询筛选出rn=1的记录,就是每个用户当天的最新签到。

用你提供的测试数据运行这段代码,会得到完全符合预期的结果:

date | user_id | office_id
2020-12-02 | 1 | D02
2020-12-02 | 2 | D01
2020-12-03 | 1 | D01

方案二:关联子查询(兼容老版本数据库)

如果你的数据库不支持窗口函数(比如MySQL 5.x),可以用这种方法来实现:

代码实现

SELECT 
    CAST(c1.checkin_datetime AS DATE) AS date,
    c1.user_id,
    c1.office_id
FROM CHECKIN_TABLE c1
LEFT JOIN CHECKIN_TABLE c2
    ON c1.user_id = c2.user_id
    AND CAST(c1.checkin_datetime AS DATE) = CAST(c2.checkin_datetime AS DATE)
    AND c1.checkin_datetime < c2.checkin_datetime
-- 找不到比当前记录更晚的签到,说明这就是当天最新的
WHERE c2.id IS NULL
ORDER BY date, user_id;

逻辑说明

通过左连接,给每条记录匹配同一个用户、同一天内签到时间更晚的记录。如果匹配不到(c2.id IS NULL),就说明这条记录是该用户当天的最后一次签到。

内容的提问来源于stack exchange,提问作者Najwan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:52:29