Sql server 多行之和的Case语句
因此,我正在为我们的会计部门创建一个工资导入文件,在报告中正确计算加班时间时遇到了问题 这是我的问题Sql server 多行之和的Case语句,sql-server,tsql,sql-server-2008,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'
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]
所以我面临的问题是,从技术上讲,第一周有加班时间,因为他们一周工作超过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
我曾考虑过做一个案例陈述,但要确定这个人在第一周的三行之间总共有40多个小时,但我不相信我能用数据的方式做到这一点
希望所有的格式都能通过。好的,我是第一次在这些论坛上发帖。如果你从你的选择和群组中删除Time\u Clk.StoreNumber,那么你就会得到你想要的结果。如果会计部门用它来确定要向哪些账户收费,那么自然你必须将其保留下来。在这种情况下,您可能需要使用窗口函数
sum(<your statement>) over (partition by EmpNum)
但这会将该值同时放在store 1和store 2行中
示例数据确实会使这变得更容易。尝试只使用整个周期的开始和结束日期。 如果给定的开始日期始终是时段开始日期,则可以根据生成的周数计算周数和组小时数。您可以使用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
我认为使用一个子查询和一个中间结果的临时表可能会很有帮助并且更容易阅读。在子查询中执行所有计算,然后对计算值执行case语句,而不是重复多次计算。即使使用临时表,我也会遇到同样的问题吗?我必须保留商店的位置,因为工资是在哪里编码的。我唯一能得到那一周总小时数的方法就是删除位置信息。
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