Oracle查询:仅获取每位员工最新访问日期的记录
问题分析
你当前的查询因为将e.description(访问类型)纳入GROUP BY子句,导致同一员工的不同访问类型会生成独立的分组记录,最终返回的是每种访问类型下的最新日期,而非员工整体的最新访问记录。使用rownum = 1只能获取全局第一条记录,无法满足“每位员工取最新访问记录”的需求。
解决方案
针对Oracle数据库(从rownum判断),推荐使用**窗口函数ROW_NUMBER()**来实现,这是处理“分组取最新/最早记录”场景的高效方案:
方法1:窗口函数(推荐,性能优且易维护)
WITH ranked_visits AS ( SELECT b.BranchName AS "Branch Name", e.EmpNo AS "Employee Number", ed.Name AS "Employee Name", e.visitdate AS "Last Visiting Date", e.description AS "Visit Type", -- 按员工编号分组,访问日期倒序排名,最新记录标记为1 ROW_NUMBER() OVER (PARTITION BY e.EmpNo ORDER BY e.visitdate DESC) AS rn FROM Employee e INNER JOIN Branch b ON e.BranchNumber = b.BranchNumber INNER JOIN EmpDetails ed ON e.EmpNo = ed.EmpNo WHERE b.BranchNumber BETWEEN '1' AND '20' AND e.visitdate > '01-AUG-2021' ) SELECT "Branch Name", "Employee Number", "Employee Name", "Last Visiting Date", "Visit Type" FROM ranked_visits WHERE rn = 1 ORDER BY b.BranchNumber;
说明:
- 用CTE(公共表表达式)先对所有符合条件的记录按员工编号分组,对每个员工的访问记录按
visitdate降序排名,最新的记录会被标记为rn=1。 - 外层查询仅筛选
rn=1的记录,即可得到每位员工最新访问的完整信息(包括对应的访问类型)。 - 若存在同一员工同一时间有多条访问记录的场景,可将
ROW_NUMBER()替换为RANK()或DENSE_RANK(),这样同日期的所有记录都会被保留,根据业务需求选择即可。
方法2:关联子查询
如果你更习惯用子查询的方式,也可以通过关联子查询获取每个员工的最新访问日期,再匹配对应记录:
SELECT b.BranchName AS "Branch Name", e.EmpNo AS "Employee Number", ed.Name AS "Employee Name", e.visitdate AS "Last Visiting Date", e.description AS "Visit Type" FROM Employee e INNER JOIN Branch b ON e.BranchNumber = b.BranchNumber INNER JOIN EmpDetails ed ON e.EmpNo = ed.EmpNo WHERE b.BranchNumber BETWEEN '1' AND '20' AND e.visitdate > '01-AUG-2021' -- 子查询获取当前员工的最新访问日期 AND e.visitdate = ( SELECT MAX(visitdate) FROM Employee WHERE EmpNo = e.EmpNo AND visitdate > '01-AUG-2021' -- 保持与外层一致的时间过滤条件 ) ORDER BY b.BranchNumber;
说明:
- 子查询会为每个员工计算其符合时间条件的最新访问日期,外层查询匹配该日期的记录。
- 若同一员工同一日期存在多条访问记录,此方法会返回所有符合的记录,可根据需求添加
DISTINCT或进一步过滤。
内容的提问来源于stack exchange,提问作者Anonymous
相关产品推荐
相关产品推荐

