在生效日期内获得员工工资

时间:2016-04-06 14:22:28

标签: sql sql-server

我要求在sql server中的给定日期范围内计算EMPLOYEE薪水

我的数据是

EMPLOYEE RATE表:

EMPL_ID EFFECTIVE_DATE  WAGE    
101        5/23/2015    20  
101        6/2/2016      30 

PROJECT表:

EMPL_ID HRS_DT  PROJECT_ID HOURS
101     1/1/2015   10001        8
101     1/2/2015   10001        8
101     1/3/2015   10001        8
 ...      ....      .....       ....
101     6/2/2016     ....        ...

预期结果:

EMPL_ID HRS_DT      PROJ_ID HR    WAGES
101     1/1/2015    10001   8      20
101     1/2/2015    10001   8      20
101     1/3/2015    10001   8      20
...      ....        ...   ...
....     6/2/2016                   30

1 个答案:

答案 0 :(得分:0)

作为起点,您可以加入empl_id列上的两个表,并忽略有效数据晚于项目日期的所有employee_rate行:

select p.empl_id, p.hrs_dt, p.project_id, p.hours, er.wage
from project p
join employee_rate er on er.empl_id = p.empl_id
and er.effective_date <= p.hrs_dt;

   EMPL_ID HRS_DT     PROJECT_ID      HOURS       WAGE
---------- ---------- ---------- ---------- ----------
       101 2016-01-01      10001          8         20
       101 2016-01-02      10001          8         20
       101 2016-01-03      10001          8         20
       101 2016-06-01      10001          8         20
...
       101 2016-06-02      10001          8         30
       101 2016-06-02      10001          8         20

...但正如您所看到的那样,一旦您发生工资变动,就会产生多重结果。因此,您只想保留最后一条记录中的工资值,其中最后一条记录是“最后一条记录”。是项目工作时间之前的最新版本。您可以使用像row_number()这样的分析函数来决定使用子查询然后过滤查找第1行的记录,该行将具有最新的生效日期:

select empl_id, hrs_dt, project_id, hours, wage
from (
  select p.empl_id, p.hrs_dt, p.project_id, p.hours, er.wage,
    row_number() over (partition by p.empl_id, p.hrs_dt
      order by er.effective_date desc) as rn
  from project p
  join employee_rate er on er.empl_id = p.empl_id
  and er.effective_date <= p.hrs_dt
) tmp
where rn = 1;

   EMPL_ID HRS_DT     PROJECT_ID      HOURS       WAGE
---------- ---------- ---------- ---------- ----------
       101 2016-01-01      10001          8         20
       101 2016-01-02      10001          8         20
       101 2016-01-03      10001          8         20
...
       101 2016-06-01      10001          8         20
       101 2016-06-02      10001          8         30

在Oracle中测试,因为这是原始问题标记,但这也适用于SQL Server。