计算剩余的加班时间

时间:2017-07-12 08:31:45

标签: sql-server tsql stored-procedures

我正在研究一个看似相当复杂的MS-SQL报告。

在公司中有一条规则规定,如果员工没有将这些时间作为空闲时间,那么人们加班时间应在30天后(在下一个工资单上)自动支付。

报告必须包含一个列表,其中包含下一个工资单上剩余的加班时间。

计算将消耗最新的小时数。

这是员工加班时间的清单(为了这个例子,只有一名员工)

person_ID   OvertimeHourDate    OVTHoursMade
123123      15.02.2017          2
123123      17.02.2017          4
123123      19.02.2017          2
123123      21.02.2017          2
123123      23.02.2017          5
123123      25.02.2017          5
123123      28.02.2017          7
123123      15.03.2017          7
123123      17.03.2017          8
123123      21.03.2017          6
123123      23.03.2017          8
123123      25.03.2017          5
123123      27.03.2017          8
123123      29.03.2017          6

例如,如果该员工没有休假,则2017年2月15日起的2小时将在30天后自动支付(更确切地说是紧随其后的工资单31.03.2017);下一行也一样。

这是空闲时间的列表。

person_ID   Date        Hours Off Taken
158223      22.02.2017      8
158223      24.02.2017      7

从前3行(最早的日期)中减去8小时的时间:2 + 4 + 2

person_ID   OvertimeHourDate    OVTHoursMade
123123      15.02.2017          2
123123      17.02.2017          4
123123      19.02.2017          2 

7小时由以下以下行计算:2 + 5

person_ID   OvertimeHourDate    OVTHoursMade
123123      21.02.2017          2
123123      23.02.2017          5

最终报告应如下所示

person_ID   Overtime Hours Remaining To Be Paid Until Next Payroll on 31.03.2017
158223                        12

所以这12小时计算如下: 由于消费了以下日期之前的几个小时,我们将仅考虑以下因素:

25.02.2017 5h
28.02.2017 7h

之后的日子没有考虑在内,因为日期超过了当前的工资单,他们将在下一个工资单上支付(31.04.2017)

看起来很复杂,我真的需要你的建议。

先谢谢你们!

1 个答案:

答案 0 :(得分:0)

如果你想每天都这样做,那么你可以将这样的日子和加班时间结合在一起,看看“总”CTE,其中包括人格,日期和加班时间以及工会与人格,日期和负面工作时间。

set dateformat  DMY
;with overtime as
(
select
*
from
(
values

(123123, cast('15.02.2017' as date),2)
,(123123,cast('17.02.2017' as date),4)
,(123123,cast('19.02.2017' as date),2)
,(123123,cast('21.02.2017' as date),2)
,(123123,cast('23.02.2017' as date),5)
,(123123,cast('25.02.2017' as date),5)
,(123123,cast('28.02.2017' as date),7)
,(123123,cast('15.03.2017' as date),7)
,(123123,cast('17.03.2017' as date),8)
,(123123,cast('21.03.2017' as date),6)
,(123123,cast('23.03.2017' as date),8)
,(123123,cast('25.03.2017' as date),5)
,(123123,cast('27.03.2017' as date),8)
,(123123,cast('29.03.2017' as date),6)

) a(person_ID,   OvertimeHourDate ,   OVTHoursMade))
,hoursoff as
(
select * from
(values

(123123,cast('22.02.2017' as date),8)
,(123123,cast('24.02.2017' as date),7)
) b(person_ID,   Date,        [Hours Off Taken]))


,total as
(
select person_ID,eomonth(OvertimeHourDate,1) eom,OvertimeHourDate [Date],OVTHoursMade [Hours] from overtime
union all
select person_ID,eomonth([date],1),[date],-[Hours Off Taken]
from hoursoff
)
select * from total

这给出了:

person_ID   eom Date    Hours
123123  31-03-2017  15-02-2017  2
123123  31-03-2017  17-02-2017  4
123123  31-03-2017  19-02-2017  2
123123  31-03-2017  21-02-2017  2
123123  31-03-2017  23-02-2017  5
123123  31-03-2017  25-02-2017  5
123123  31-03-2017  28-02-2017  7
123123  30-04-2017  15-03-2017  7
123123  30-04-2017  17-03-2017  8
123123  30-04-2017  21-03-2017  6
123123  30-04-2017  23-03-2017  8
123123  30-04-2017  25-03-2017  5
123123  30-04-2017  27-03-2017  8
123123  30-04-2017  29-03-2017  6
123123  31-03-2017  22-02-2017  -8
123123  31-03-2017  24-02-2017  -7

“EOM”栏是支付工资的日期。

现在,我们使用两个分析函数sum和rownumber:

代替las“select * from total”使用此:

select 
    person_ID
    ,eom
    ,Date
    ,Hours
    ,sum(Hours) over (partition by person_ID,eom order by date) TotHours
    ,row_number() over (partition by person_ID,eom order by date desc) rn
from total
order by date

这给了我们一个小时的运行总计,而rn列每个月给出一个递减的条目数,所以最后一个有rn = 1

person_ID   eom Date    Hours   TotHours    rn
123123  2017-03-31  2017-02-15  2   2   9
123123  2017-03-31  2017-02-17  4   6   8
123123  2017-03-31  2017-02-19  2   8   7
123123  2017-03-31  2017-02-21  2   10  6
123123  2017-03-31  2017-02-22  -8  2   5
123123  2017-03-31  2017-02-23  5   7   4
123123  2017-03-31  2017-02-24  -7  0   3
123123  2017-03-31  2017-02-25  5   5   2
123123  2017-03-31  2017-02-28  7   12  1
123123  2017-04-30  2017-03-15  7   7   7
123123  2017-04-30  2017-03-17  8   15  6
123123  2017-04-30  2017-03-21  6   21  5
123123  2017-04-30  2017-03-23  8   29  4
123123  2017-04-30  2017-03-25  5   34  3
123123  2017-04-30  2017-03-27  8   42  2
123123  2017-04-30  2017-03-29  6   48  1

员工工资加班时数由:

找到
set dateformat  DMY
;with overtime as
(
select
*
from
(
values

(123123, cast('15.02.2017' as date),2)
,(123123,cast('17.02.2017' as date),4)
,(123123,cast('19.02.2017' as date),2)
,(123123,cast('21.02.2017' as date),2)
,(123123,cast('23.02.2017' as date),5)
,(123123,cast('25.02.2017' as date),5)
,(123123,cast('28.02.2017' as date),7)
,(123123,cast('15.03.2017' as date),7)
,(123123,cast('17.03.2017' as date),8)
,(123123,cast('21.03.2017' as date),6)
,(123123,cast('23.03.2017' as date),8)
,(123123,cast('25.03.2017' as date),5)
,(123123,cast('27.03.2017' as date),8)
,(123123,cast('29.03.2017' as date),6)

) a(person_ID,   OvertimeHourDate ,   OVTHoursMade))
,hoursoff as
(
select * from
(values

(123123,cast('22.02.2017' as date),8)
,(123123,cast('24.02.2017' as date),7)
) b(person_ID,   Date,        [Hours Off Taken]))


,total as
(
select person_ID,eomonth(OvertimeHourDate,1) eom,OvertimeHourDate [Date],OVTHoursMade [Hours] from overtime
union all
select person_ID,eomonth([date],1),[date],-[Hours Off Taken]
from hoursoff
)
select person_id,eom,TotHours 
from
(
select 
    person_ID
    ,eom
    ,Date
    ,Hours
    ,sum(Hours) over (partition by person_ID,eom order by date) TotHours
    ,row_number() over (partition by person_ID,eom order by date desc) rn
from total
) a
where rn=1