多行总和的案例声明

时间:2018-11-09 18:36:16

标签: sql-server tsql sql-server-2008

所以我正在为会计部门创建工资单导入文件,但是我无法在报告中正确计算加班费。

这是我的查询

declare @week1start date
declare @week1end date
declare @week2start date
declare @week2end date

--Week 1 Start and End
set @week1start = CAST('10/15/2018' as date)
set @week1end = CAST('10/21/2018' as date)

--Week 2 Start and End
set @week2start = CAST('10/22/2018' as date)
set @week2end = CAST('10/28/2018' as date)

--Week 1 Hours Worked

(select Employee.EMPLOYEE_NUM as [Employee Num],Employee.NAME as [Employee Name],Time_Clk.StoreNumber as [Store],

[Week 1 Hours Worked]= case
when (sum(cast(cast(DATEDIFF(MINUTE,IN_TIME,OUT_TIME) as decimal (10,2))/60 as decimal (10,2)))) - 40 > 0
then 40
else (sum(cast(cast(DATEDIFF(MINUTE,IN_TIME,OUT_TIME) as decimal (10,2))/60 as decimal (10,2))))
end,

[Week 1 OT Hours] = case
when (sum(cast(cast(DATEDIFF(MINUTE,IN_TIME,OUT_TIME) as decimal (10,2))/60 as decimal (10,2)))) - 40 > 0
then (sum(cast(cast(DATEDIFF(MINUTE,IN_TIME,OUT_TIME) as decimal (10,2))/60 as decimal (10,2)))) -40
else 0
end,
0 as [Week 2 Hours Worked],
0 as [Week 2 OT Hours]

from Time_Clk
join Employee on Time_Clk.EMPLOYEE_ID = Employee.EMPLOYEE_NUM

where CAST(out_time as DATE) >= @week1start and CAST(out_time as date) <= @week1end and Time_Clk.OUT_TYPE = 1

group by Employee.EMPLOYEE_NUM,Employee.NAME,Time_Clk.StoreNumber)

union all

--Week 2 hours worked

(select Employee.EMPLOYEE_NUM as [Employee Num],Employee.NAME as [Employee Name],Time_Clk.StoreNumber as [Store],

0 as [Week 1 Hours Worked],
0 as [Week 1 OT Hours],

[Week 2 Hours Worked] = case
when (sum(cast(cast(DATEDIFF(MINUTE,IN_TIME,OUT_TIME) as decimal (10,2))/60 as decimal (10,2)))) - 40 > 0
then 40
else (sum(cast(cast(DATEDIFF(MINUTE,IN_TIME,OUT_TIME) as decimal (10,2))/60 as decimal (10,2))))
end,

[Week 2 OT Hours] = case
when (sum(cast(cast(DATEDIFF(MINUTE,IN_TIME,OUT_TIME) as decimal (10,2))/60 as decimal (10,2)))) - 40 > 0
then (sum(cast(cast(DATEDIFF(MINUTE,IN_TIME,OUT_TIME) as decimal (10,2))/60 as decimal (10,2)))) -40
else 0
end

from Time_Clk
join Employee on Time_Clk.EMPLOYEE_ID = Employee.EMPLOYEE_NUM

where CAST(out_time as DATE) >= @week2start and CAST(out_time as date) <= @week2end and Time_Clk.OUT_TYPE = 1

group by Employee.EMPLOYEE_NUM,Employee.NAME,Time_Clk.StoreNumber)

order by [Employee Num]

所以我的大部分输出都很好,但这是针对特定用户的选择输出

 EmpNum EmpName  Store  Week 1 Hrs  Week 1 OT   Week 2 Hours    Week 2 OT 
    1   Name    1       0.00        0.00          40.00         0.88
    1   Name    1       39.20       0.00          0.00          0.00
    1   Name    2       5.23        0.00          0.00         0.00   

因此,我面临的问题是,从技术上讲,第1周有加班时间,因为他们那一周在两个不同的位置工作了40多个小时。理想情况下,结果看起来像

EmpNum  EmpName  Store  Week 1 Hrs  Week 1 OT   Week 2 Hours    Week 2 OT 
    1   Name    1       0.00        0.00          40.00         0.88
    1   Name    1       39.20       0.00          0.00          0.00
    1   Name    2       0.80        4.43          0.00         0.00   

我考虑过做一个案例陈述,但要确定该人在第1周的所有3条线之间总共有40个小时以上的时间,但是我不相信我可以用数据的方式做到这一点。

希望所有格式都可以通过ok,我是刚开始在这些论坛上发布内容的人。

2 个答案:

答案 0 :(得分:0)

如果从Time_Clk.StoreNumberSELECT中删除GROUP BY,那么您将获得想要的结果。如果会计使用此功能确定要向哪个帐户收费,那么自然就必须保留它。在这种情况下,您可能需要使用窗口功能。

sum(<your statement>) over (partition by EmpNum)

但是这会将值放置在存储1和存储2的行中。

样本数据确实可以简化这一过程。

答案 1 :(得分:0)

尝试仅使用开始日期和结束日期来表示整个星期。 如果给定的开始日期始终是期间开始日期,则可以通过得出的星期数来计算星期数和小组时间。您可以使用datepart或仅使用mod 7(%)(如果您使用某些财政日历)。

一旦拥有了垂直形式,就可以做一些关键的魔术来获得想要的结果。

也许是这样的...

if object_id('employee') is not null drop table employee
if object_id('timeclock') is not null drop table timeclock
Go

CREATE TABLE employee (employeeid int identity(1,1), name varchar(50)) ;
GO
CREATE TABLE timeclock (id int identity(1,1), employeeid int, IN_TIME datetime, OUT_TIME datetime);
Go
insert into employee
  (name) 
 values (CHAR(ABS(CHECKSUM(NEWID()))%26+65))
GO 5

;WITH [days] AS
(
    SELECT 1 AS [day]
    UNION ALL
    SELECT [day]+1
        FROM [days] 
        WHERE [day] < 20

)
INSERT INTO timeclock
Select employeeid, GetDate()+[day], Dateadd(hh,8, GETDATE()+[day])
from employee
CROSS APPLY [days]


declare @start datetime = '11/12/2018';
declare @end datetime = @start + 15



;with aggregatedata
as
(
    select 
        employee.employeeid
        , employee.name
        ,weeknum = ROW_NUMBER() over (partition by employee.employeeid order by employee.employeeid, DATEPART(week, In_time) )
        ,[hours] = sum(DATEDIFF(Minute,IN_TIME,OUT_TIME)) 
    from employee
        inner join timeclock on employee.employeeid = timeclock.employeeid
    WHERE
        in_time > @start and OUT_TIME < @end
    group by employee.employeeid, employee.name, DATEPART(week, In_time)
)

select
    employeeid, [name], [1], [2], [3], [4]
from aggregatedata
PIVOT 
(
    sum([hours])
    for weeknum in ([1], [2], [3], [4])
) as pvt