我有两个表-一个表涉及员工活动,另一个表涉及employee_status。问题是员工状态随时间而变化,因此我需要像会议时一样加入状态。
>>> employee_activity
id session_start
emp1 1/1/2019
emp1 2/22/2019
emp1 3/1/2019
emp2 1/4/2019
emp2 2/23/2019
>>> employee_status
id status effective date
emp1 a 1/1/2018
emp1 b 2/1/2019
emp1 c 3/5/2019
emp2 a 6/1/2018
emp2 b 1/1/2019
所以我开始写一些东西,以确保它在活动结束后会忽略状态,但是我在弄清楚如何只选择最新状态方面有些挣扎。查询只需要将状态与最大 小于会话开始日期
SELECT * FROM employee_activity a
LEFT join employee_status s on a.id = s.id WHERE s.effective_date <= a.session_start
-- how do I join only the most recent status?
上面两个表的期望输出将是
>>> my_output
id session_start status
emp1 1/1/2019 a
emp1 2/22/2019 b
emp1 3/1/2019 b
emp2 1/4/2019 b
emp2 2/23/2019 b
谢谢!
答案 0 :(得分:2)
首先从状态计算有效间隔,即,您没有开始EFFECTIVE_DATE
的开始和结束时间戳。
请注意,我使用默认的开放结束日期,并从结束日期中减去一秒钟以获取封闭间隔,可以使用BETWEEN
来查询封闭间隔。
比键上的简单连接和添加时间之间的约束:
with emp as (
select ID, STATUS, EFFECTIVE_DATE status_valid_from,
lead(EFFECTIVE_DATE - INTERVAL '1' SECOND,1,DATE'2500-01-01')
over (partition by id order by EFFECTIVE_DATE) as status_valid_to
from employee_status)
SELECT a.id, a.SESSION_START, s.STATUS, s.STATUS_VALID_FROM
FROM employee_activity a
LEFT join emp s
on a.id = s.id and session_start between s.status_valid_from and s.status_valid_to
order by 1,2;
ID SESSION_START S STATUS_VALID_FROM
---- ------------------- - -------------------
emp1 01.01.2019 00:00:00 a 01.01.2018 00:00:00
emp1 22.02.2019 00:00:00 b 01.02.2019 00:00:00
emp1 01.03.2019 00:00:00 b 01.02.2019 00:00:00
emp2 04.01.2019 00:00:00 b 01.01.2019 00:00:00
emp2 23.02.2019 00:00:00 b 01.01.2019 00:00:00
样本数据
create table employee_activity as
select 'emp1' id, to_date('1/1/2019','mm/dd/yyyy') session_start from dual union all
select 'emp1' id, to_date('2/22/2019','mm/dd/yyyy') session_start from dual union all
select 'emp1' id, to_date('3/1/2019','mm/dd/yyyy') session_start from dual union all
select 'emp2' id, to_date('1/4/2019','mm/dd/yyyy') session_start from dual union all
select 'emp2' id, to_date('2/23/2019','mm/dd/yyyy') session_start from dual;
create table employee_status as
select 'emp1' id, 'a'status, to_date('1/1/2018','mm/dd/yyyy') effective_date from dual union all
select 'emp1' id, 'b'status, to_date('2/1/2019','mm/dd/yyyy') effective_date from dual union all
select 'emp1' id, 'c'status, to_date('3/5/2019','mm/dd/yyyy') effective_date from dual union all
select 'emp2' id, 'a'status, to_date('6/1/2018','mm/dd/yyyy') effective_date from dual union all
select 'emp2' id, 'b'status, to_date('1/1/2019','mm/dd/yyyy') effective_date from dual;
答案 1 :(得分:0)
您可以使用相关子查询来做到这一点:
select ea.*,
(select max(es.status) keep (dense_rank first order by es.effective_date desc)
from employee_status es
where es.id = ea.id and es.effective_date <= ea.session_start
) as status
from employee_activity ea;
在Oracle 12C +中,更加直观:
select ea.*,
(select es.status
from employee_status es
where es.id = ea.id and es.effective_date <= ea.session_start
order by es.effective_date desc
fetch first 1 row only
) as status
from employee_activity ea;