使用SQL查找员工的时间级别更改

时间:2017-05-31 16:35:34

标签: sql

我正在努力寻找一种方法来确定员工升级所需的时间。

我有两张桌子:

EMPLOYEE_DAILY:包含员工数据的每日快照。

EMP_HISTORY:包含促销活动,当前(促销前)级别,促销级别和促销日期。

我原来的解决方案是查看EMP_HISTORY表中的促销事件,然后在EMPLOYEE_DAILY表中获取员工处于促销前级别的第一个日期,然后从促销日期中减去该日期以确定时间员工升级了。

我的方法存在问题,因为员工经常离开公司,然后返回(有时多次),所以如果员工来自之前的工作周期,我的查询将把员工的第一个日期拉到CURRENT_LEVEL(从而使时间升级)。

WITH LEVEL_DATES AS
(
SELECT
    EMPLOYEE_ID,
    EMPLOYEE_LEVEL,
    MIN(AS_OF_DATE) AS MIN_LEVEL_DATE
FROM EMPLOYEE_DAILY
)
SELECT
    H.EMPLOYEE_ID,
    H.PROCESS_TYPE,
    H.CURRENT_LEVEL,
    H.PROMOTION_LEVEL
    H.EFFECTIVE_DATE,
    LD.MIN_LEVEL_DATE
FROM EMP_HIST H
LEFT JOIN LEVEL_DATES LD
ON H.EMPLOYEE_ID = LD.EMPLOYEE_ID
AND H.PROMOTION_LEVEL != LD.EMPLOYEE_LEVEL

有没有人对如何提取准确的时间到级别变化数据有所了解;促销前的第一个日期在员工的工作间隔内。我正在使用Oracle数据库。

示例场景: 员工1234于2015年1月1日在L1受雇 在2015年3月5日被提升为L2 离开公司于2015年4月1日 于2017年1月1日在L1重新雇用 2017年3月1日升级到L2

示例数据:

EMPLOYEE_DAILY:
EMPLOYEE_ID    EMPLOYEE_LEVEL    AS_OF_DATE
1234            L1               2015-03-02
1234            L1               2015-03-03
1234            L1               2015-03-04
1234            L2               2015-03-05

示例数据:

EMPLOYEE_HIST:
EMPLOYEE_ID  EFFECTIVE_DATE  CURRENT_LEVEL PROMOTION_LEVEL 
PROCESS_TYPE

1234         2015-03-05      L1            L2
PROMOTION

我相信我的查询会查看3/1/2017促销并拉出2015年1月1日的日期,但我真正想要的是一个查询,它会显示各个促销级别之间的时间,所以3/5 / 2015年 - 2015年1月1日和3/1/2017 - 1/1/2017。

1 个答案:

答案 0 :(得分:0)

我没有运行此程序来验证语法的准确性或正确性,但您可以尝试:

select
  employee_id
  ,earliest_as_of_date as effective_date
  ,prev_employee_level as current_level
  ,employee_level promotion_level
from (
  select 
     employee_id
     ,employee_level
     ,case when lag(employee_id,1) over (order by employee_id, as_of_date) <> employee_id then null -- first row for an employee, can't be a promotion
           when lag(employee_level,1) over (order by employee_id, as_of_date) = employee_level then null -- same level as previous row for this employee, is not a promotion
           else lag(employee_level,1) over (order by employee_id, as_of_date) as prev_employee_level
     ,min(as_of_date) over (partition by employee_id,employee_level) as earliest_as_of_date
  from
    employee_daily
  group by 1,2
) a
where 1=1
  and prev_employee_level is not null