Oracle表中存在日期范围重叠的员工履历记录查询咨询
找出Oracle表中存在履历日期重叠的员工注册编号
嘿,这个问题很常见,我来给你详细讲讲怎么解决!要找出存在日期范围重叠记录的Registration_No,我们不需要特别冷门的Oracle函数,用基础的日期比较、自连接或者分析函数就能搞定,下面给你两种实用的方法:
方法一:自连接查询(直观易懂)
这种方式是把表和自己做连接,匹配同一员工的不同履历记录,判断它们的日期范围是否重叠。
实现SQL
SELECT DISTINCT a.REGISTRATION_NO FROM A a INNER JOIN A b ON a.REGISTRATION_NO = b.REGISTRATION_NO AND a.ROWID <> b.ROWID -- 排除同一条记录自己匹配自己的情况 AND a.JOIN_DATE < b.RESG_DATE AND b.JOIN_DATE < a.RESG_DATE;
逻辑解释
- 用
REGISTRATION_NO关联同一员工的不同记录,ROWID <> b.ROWID避免同一条记录自我匹配; - 核心的重叠判断条件:两个日期区间
[a.JOIN_DATE, a.RESG_DATE]和[b.JOIN_DATE, b.RESG_DATE]重叠的标准是**a的入职日期 < b的离职日期且b的入职日期 < a的离职日期**,这个条件能覆盖所有重叠场景(包含、交叉等); DISTINCT用来去重,因为同一员工的重叠记录会被双向匹配两次,去重后得到唯一的员工编号。
方法二:分析函数LAG(高效简洁)
如果数据量较大,用分析函数LAG会更高效,它能帮我们在分组排序后直接获取上一条记录的离职日期,然后和当前记录的入职日期做比较。
实现SQL
SELECT DISTINCT REGISTRATION_NO FROM ( SELECT REGISTRATION_NO, JOIN_DATE, RESG_DATE, -- 按员工分组、入职日期排序,获取上一条记录的离职日期 LAG(RESG_DATE) OVER (PARTITION BY REGISTRATION_NO ORDER BY JOIN_DATE) AS PREV_RESIGN_DATE FROM A ) t -- 如果当前入职日期早于上一条的离职日期,说明两条履历重叠 WHERE JOIN_DATE < PREV_RESIGN_DATE;
逻辑解释
LAG(RESG_DATE) OVER (PARTITION BY REGISTRATION_NO ORDER BY JOIN_DATE):这个分析函数的作用是,把数据按REGISTRATION_NO分组,每组内按JOIN_DATE排序,然后给每条记录添加上一条记录的RESG_DATE;- 外层查询中,只要当前记录的
JOIN_DATE小于上一条的PREV_RESIGN_DATE,就说明这两条履历的日期范围有重叠; - 同样用
DISTINCT去重,确保每个员工编号只出现一次。
验证你的示例数据
用你提供的测试数据执行上面任意一个SQL,都会得到结果:100和102,这正好对应你提到的有重叠的黄色标记区域,完美符合预期。
关于Oracle函数的说明
这里用到的LAG是Oracle的分析函数,专门用于处理分组排序后相邻记录的比较,非常适合这类场景。除此之外,我们只用到了基础的日期比较逻辑,不需要额外的特殊日期函数——如果你的数据是字符串格式,可能需要用TO_DATE转换,但你的示例数据已经是DATE类型,所以直接用即可。
内容的提问来源于stack exchange,提问作者Hudhaifa Yoosuf
相关产品推荐
相关产品推荐

