根据两个日期之间的周/年计算OT

时间:2019-09-20 17:46:37

标签: sql sql-server

我们每月支付两次。付款时间为1月15日至16日。因此,付款期的结束可以在任何一天结束。

我们根据周一至周日超过40小时的时间支付加班费。

如果支付期在周六结束,并且员工有47个小时,我们将在该支票上支付7个小时。.如果员工在周日工作,那么现在一周的总时数是52 ..我们将在5个小时内支付他们的下一次检查。现在是手动计算过程。

我正在努力处理如何编写查询,以使我获得额外的收益。

这是我上次支付期间9/1/2019至9/15/2019的每日工作总量的输出,并且自1日为周日起。我需要从8 / 26/2019。他在这个特殊的员工上周末工作。在8/16/2019至8/31/2019的支付期间内,他获得了6.28小时的加班费,并在9/1/2019额外工作了两个小时,因此需要将2个小时的加班时间结转到9/1 / 2019至9/15/2019检查。

ID HRS WK CDATE STU02 8.16 35 2019-08-26 00:00:00.000 STU02 9.37 35 2019-08-27 00:00:00.000 STU02 9.07 35 2019-08-28 00:00:00.000 STU02 7.91 35 2019-08-29 00:00:00.000 STU02 9.12 35 2019-08-30 00:00:00.000 STU02 2.65 35 2019-08-31 00:00:00.000 STU02 2.00 35 2019-09-01 00:00:00.000 STU02 4.17 36 2019-09-02 00:00:00.000 STU02 9.40 36 2019-09-03 00:00:00.000 STU02 8.80 36 2019-09-04 00:00:00.000 STU02 8.90 36 2019-09-05 00:00:00.000 STU02 8.93 36 2019-09-06 00:00:00.000 STU02 2.56 36 2019-09-07 00:00:00.000 STU02 2.00 36 2019-09-08 00:00:00.000 STU02 8.66 37 2019-09-09 00:00:00.000 STU02 9.14 37 2019-09-10 00:00:00.000 STU02 9.07 37 2019-09-11 00:00:00.000 STU02 9.29 37 2019-09-12 00:00:00.000 STU02 9.94 37 2019-09-13 00:00:00.000 STU02 2.00 37 2019-09-15 00:00:00.000

我很感谢这个尝试使我疯狂,尝试过许多不同的事情。

**使用表和数据更新**

/****** Object:  Table [dbo].[DLI_TEST_DATE]    Script Date: 9/18/2019 3:50:50 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[DLI_TEST_DATE](
    [EMPLOYEE_ID] [nvarchar](15) NULL,
    [REG_TOTAL] [float] NULL,
    [WEEK_NUM] [int] NULL,
    [CDATE] [datetime] NULL,
    [DAYOFWK] [int] NULL
) ON [PRIMARY]

GO

INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 2, 35, CAST(N'2019-08-25 00:00:00.000' AS DateTime), 1)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 8.16, 35, CAST(N'2019-08-26 00:00:00.000' AS DateTime), 2)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 9.37, 35, CAST(N'2019-08-27 00:00:00.000' AS DateTime), 3)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 9.07, 35, CAST(N'2019-08-28 00:00:00.000' AS DateTime), 4)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 7.91, 35, CAST(N'2019-08-29 00:00:00.000' AS DateTime), 5)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 9.12, 35, CAST(N'2019-08-30 00:00:00.000' AS DateTime), 6)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 2.65, 35, CAST(N'2019-08-31 00:00:00.000' AS DateTime), 7)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 2, 36, CAST(N'2019-09-01 00:00:00.000' AS DateTime), 1)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 4.17, 36, CAST(N'2019-09-02 00:00:00.000' AS DateTime), 2)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 9.4, 36, CAST(N'2019-09-03 00:00:00.000' AS DateTime), 3)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 8.8, 36, CAST(N'2019-09-04 00:00:00.000' AS DateTime), 4)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 8.9, 36, CAST(N'2019-09-05 00:00:00.000' AS DateTime), 5)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 8.93, 36, CAST(N'2019-09-06 00:00:00.000' AS DateTime), 6)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 2.56, 36, CAST(N'2019-09-07 00:00:00.000' AS DateTime), 7)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 2, 37, CAST(N'2019-09-08 00:00:00.000' AS DateTime), 1)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 8.66, 37, CAST(N'2019-09-09 00:00:00.000' AS DateTime), 2)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 9.14, 37, CAST(N'2019-09-10 00:00:00.000' AS DateTime), 3)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 9.07, 37, CAST(N'2019-09-11 00:00:00.000' AS DateTime), 4)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 9.29, 37, CAST(N'2019-09-12 00:00:00.000' AS DateTime), 5)
GO
INSERT [dbo].[DLI_TEST_DATE] ([EMPLOYEE_ID], [REG_TOTAL], [WEEK_NUM], [CDATE], [DAYOFWK]) VALUES (N'STU02', 9.94, 37, CAST(N'2019-09-13 00:00:00.000' AS DateTime), 6)
GO

2 个答案:

答案 0 :(得分:0)

子查询在适用的情况下将给定的星期数分成2个不同的支付期。 where子句仅包括加班的几周,分为两个工资期。 选择包括加班的数学。

declare @DLI_TEST_DATA TABLE (
    [EMPLOYEE_ID] [nvarchar](15) NULL,
    [REG_TOTAL] [float] NULL,
    [WEEK_NUM] [int] NULL,
    [CDATE] [datetime] NULL,
    [DAYOFWK] [int] NULL
) 

INSERT into @DLI_TEST_DATA
    VALUES (N'STU02', 2, 34, CAST(N'2019-08-25 00:00:00.000' AS DateTime), 1)
        ,(N'STU02', 8.16, 35, CAST(N'2019-08-26 00:00:00.000' AS DateTime), 2)
        ,(N'STU02', 9.37, 35, CAST(N'2019-08-27 00:00:00.000' AS DateTime), 3)
        ,(N'STU02', 9.07, 35, CAST(N'2019-08-28 00:00:00.000' AS DateTime), 4)
        ,(N'STU02', 7.91, 35, CAST(N'2019-08-29 00:00:00.000' AS DateTime), 5)
        ,(N'STU02', 9.12, 35, CAST(N'2019-08-30 00:00:00.000' AS DateTime), 6)
        ,(N'STU02', 2.65, 35, CAST(N'2019-08-31 00:00:00.000' AS DateTime), 7)
        ,(N'STU02', 2, 35, CAST(N'2019-09-01 00:00:00.000' AS DateTime), 1)
        ,(N'STU02', 4.17, 36, CAST(N'2019-09-02 00:00:00.000' AS DateTime), 2)
        ,(N'STU02', 9.4, 36, CAST(N'2019-09-03 00:00:00.000' AS DateTime), 3)
        ,(N'STU02', 8.8, 36, CAST(N'2019-09-04 00:00:00.000' AS DateTime), 4)
        ,(N'STU02', 8.9, 36, CAST(N'2019-09-05 00:00:00.000' AS DateTime), 5)
        ,(N'STU02', 8.93, 36, CAST(N'2019-09-06 00:00:00.000' AS DateTime), 6)
        ,(N'STU02', 2.56, 36, CAST(N'2019-09-07 00:00:00.000' AS DateTime), 7)
        ,(N'STU02', 2, 36, CAST(N'2019-09-08 00:00:00.000' AS DateTime), 1)
        ,(N'STU02', 8.66, 37, CAST(N'2019-09-09 00:00:00.000' AS DateTime), 2)
        ,(N'STU02', 9.14, 37, CAST(N'2019-09-10 00:00:00.000' AS DateTime), 3)
        ,(N'STU02', 9.07, 37, CAST(N'2019-09-11 00:00:00.000' AS DateTime), 4)
        ,(N'STU02', 9.29, 37, CAST(N'2019-09-12 00:00:00.000' AS DateTime), 5)
        ,(N'STU02', 9.94, 37, CAST(N'2019-09-13 00:00:00.000' AS DateTime), 6)

select WEEK_NUM,fullweek - (case when endfirstperiod+endsecondperiod <= 40 then 40.0 else endfirstperiod+endsecondperiod end) OvertimeCarriedOver
from (
    select week_num,sum(reg_total) fullweek
        ,sum(case when day(cdate) between 10 and 15 then reg_total else 0 end) endfirstperiod
        ,sum(case when day(cdate) between 16 and 21 then reg_total else 0 end) beginsecondperiod
        ,sum(case when day(cdate) between day(eomonth(cdate)) - 5 and day(eomonth(cdate)) then reg_total else 0 end) endsecondperiod
        ,sum(case when day(cdate) between 1 and 6 then reg_total else 0 end) beginfirstperiod
    from @DLI_TEST_DATA
    group by week_num
) basic
where fullweek > 40.0
    and beginfirstperiod+beginsecondperiod > 0
    and endfirstperiod+endsecondperiod > 0
order by week_num

答案 1 :(得分:0)

核心思想是将所有内容分组为合乎逻辑的星期,然后查看与其相关的薪酬期与该周的第一天不匹配的日期。

engine 1 | | | | env 1 env 2 是从那几天开始的小时数。根据第40小时的工作时间,该数字可能会太高。在最终输出中,该数据以该周的总加班时间为上限。

Create table "order" (
order_id int,
item_type varchar(50),
item_name varchar(50),
item_price decimal(10,2),
primary key(order_id)
);

insert into "order" values (1, 'Item', 'Name', '20.2');

select * from "order";

https://rextester.com/TVXF30798

顺便说一句,您真的不想使用carryover_max作为数据类型。

由于存在关于周编号的问题,我只是计算了日期。无论如何,这应该在整个新年期间都可以更好地工作。另外,我确实假设您的服务器设置在使用with weeks as ( select week_start, week_end, case when sum(REG_TOTAL) > 40 then sum(REG_TOTAL) - 40 else 0 end as overtime_total, case when sum(REG_TOTAL) > 40 then sum(case when period <> week_period then REG_TOTAL else 0 end) else 0 end carryover_max from dbo.DLI_TEST_DATE cross apply ( select dateadd(day, -datepart(weekday, dateadd(day, -1, cdate)) + 1, cdate) ) as v(week_start) cross apply ( select dateadd(day, 6, week_start), case when datepart(day, week_start) <= 15 then 1 else 2 end, case when datepart(day, cdate) <= 15 then 1 else 2 end ) as v2(week_end, week_period, period) group by week_start, week_end ), periods as ( select distinct period_start, period_end from dbo.DLI_TEST_DATE cross apply ( select datefromparts(datepart(year, cdate), datepart(month, cdate), case when datepart(day, cdate) <= 15 then 1 else 15 end), datefromparts(datepart(year, cdate), datepart(month, cdate), case when datepart(day, cdate) <= 15 then 16 else datepart(day, eomonth(cdate)) end) ) v(period_start, period_end) ) select period_start, sum(case when carryover_max > overtime_total then overtime_total else carryover_max end) as overtime_owed from periods inner join weeks w on w.week_end >= period_start and w.week_end <= period_end group by period_start; 时将星期天作为一周的第一天。