SQL实现:获取同一人员同一班次当日最新Login记录并去重
问题描述
现有一张包含DepDate(日期)、FirstName(名)、LastName(姓)、ID(员工ID)、ClassNum(班次编号)、Dept、Arri、Posit(岗位)、Login(登录时间)字段的数据表。存在同一员工(按ID识别)在同一ClassNum、同一DepDate下,以不同Posit多次登录的情况,需要保留该员工对应班次当日最新的Login记录。之前仅用max(Login)的方式仍会存在重复数据,需实现获取最新Login记录并剔除其他不同Posit的记录。
示例数据表:
| DepDate | FirstName | LastName | ID | ClassNum | Dept | Arri | Posit | Login |
|---|---|---|---|---|---|---|---|---|
| 2022-02-12 | Matt | Map | ABC123 | 4532 | 05:32 | 12:34 | Line Leader | 05:00 |
| 2022-02-12 | Matt | Map | ABC123 | 4532 | 05:32 | 12:34 | Line Ender | 05:30 |
| 2022-02-12 | Matt | Map | ABC123 | 4532 | 05:32 | 12:34 | Line Middle | 04:30 |
| 2022-01-09 | Emma | Cruise | ACG123 | 4532 | 05:32 | 12:34 | Door Holder | 03:30 |
解决方案
方法一:使用窗口函数ROW_NUMBER()(推荐)
这是处理这类「每组取最新记录」问题最简洁高效的方式,通过窗口函数给同一分组内的记录按Login倒序排名,只保留排名第一的记录。
假设表名为employee_logs,SQL语句如下:
SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY DepDate, ID, ClassNum ORDER BY Login DESC ) AS rn FROM employee_logs ) t WHERE rn = 1;
说明:
PARTITION BY DepDate, ID, ClassNum:按日期、员工ID、班次编号分组,确保仅在同一员工同一班次同一日期内排名。ORDER BY Login DESC:在每组内按登录时间倒序排列,最新的记录排名为1。- 外层查询筛选
rn = 1的记录,即为每组的最新登录记录。
针对示例数据,执行后会得到:
| DepDate | FirstName | LastName | ID | ClassNum | Dept | Arri | Posit | Login | rn |
|---|---|---|---|---|---|---|---|---|---|
| 2022-02-12 | Matt | Map | ABC123 | 4532 | 05:32 | 12:34 | Line Ender | 05:30 | 1 |
| 2022-01-09 | Emma | Cruise | ACG123 | 4532 | 05:32 | 12:34 | Door Holder | 03:30 | 1 |
方法二:关联子查询
如果你的数据库不支持窗口函数(如旧版MySQL),可以用关联子查询筛选最新记录:
SELECT el.* FROM employee_logs el WHERE Login = ( SELECT MAX(Login) FROM employee_logs el2 WHERE el2.DepDate = el.DepDate AND el2.ID = el.ID AND el2.ClassNum = el.ClassNum );
说明:
- 子查询找到每个
DepDate + ID + ClassNum分组下的最大Login时间。 - 外层查询匹配对应分组中登录时间等于最大值的记录,实现保留最新记录。
注意:如果同一分组内有多条记录Login时间完全相同,这个方法会返回所有这些记录;若需确保唯一,仍推荐使用窗口函数方案(可在ORDER BY中添加Posit等字段打破平局)。
内容的提问来源于stack exchange,提问作者confused101
相关产品推荐
相关产品推荐

