请求编写SQL查询:按用户和时间分组考勤表并筛选在现场用户
现场用户考勤查询解决方案
原始考勤数据
| User | In | Out |
|---|---|---|
| User 1 | 31.10.2023 04:20 | |
| User 1 | 31.10.2023 05:20 | |
| User 1 | 31.10.2023 05:25 | |
| User 2 | 31.10.2023 02:20 | |
| User 3 | 31.10.2023 03:00 | |
| User 3 | 31.10.2023 05:20 | |
| User 3 | 31.10.2023 05:21 |
预期结果
| User | In |
|---|---|
| User 1 | 31.10.2023 05:25 |
| User 2 | 31.10.2023 02:20 |
SQL查询语句
通用版本(时间字段为日期类型)
假设表名为attendance,字段为user_name(对应用户名)、in_time(签到时间)、out_time(签退时间):
WITH user_latest_records AS ( SELECT user_name, in_time, out_time, ROW_NUMBER() OVER ( PARTITION BY user_name ORDER BY COALESCE(out_time, in_time) DESC ) AS rn FROM attendance ) SELECT user_name AS User, in_time AS In FROM user_latest_records WHERE rn = 1 AND in_time IS NOT NULL;
MySQL适配版本(时间字段为字符串格式)
如果签到/签退时间是字符串类型,需先转换为日期格式再排序:
WITH user_latest_records AS ( SELECT user_name, in_time, out_time, ROW_NUMBER() OVER ( PARTITION BY user_name ORDER BY COALESCE( STR_TO_DATE(out_time, '%d.%m.%Y %H:%i'), STR_TO_DATE(in_time, '%d.%m.%Y %H:%i') ) DESC ) AS rn FROM attendance ) SELECT user_name AS User, in_time AS In FROM user_latest_records WHERE rn = 1 AND in_time IS NOT NULL;
逻辑说明
- 用
ROW_NUMBER()窗口函数按用户分组,对每个用户的考勤记录按最新时间排序(优先取签退时间,无签退则取签到时间),标记每条记录的排序序号rn。 - 筛选出每个用户的最新记录(
rn=1),且该记录为签到状态(in_time不为空),这类用户即为当前在现场的用户。
内容的提问来源于stack exchange,提问作者DjDeD
相关产品推荐
相关产品推荐

