Sql 从多行收集的已用时间总和
我试图根据团队全天执行的工作类型,显示他们的生产率与非生产率百分比。我可以用下面的代码成功地实现我想要的格式,但是如果一名员工在一天内在两个单独的部门工作,子查询将失败,因为它返回多行 这就是我现在的工作Sql 从多行收集的已用时间总和,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我试图根据团队全天执行的工作类型,显示他们的生产率与非生产率百分比。我可以用下面的代码成功地实现我想要的格式,但是如果一名员工在一天内在两个单独的部门工作,子查询将失败,因为它返回多行 这就是我现在的工作 DECLARE @Offset INT , @Start DATETIME , @Loc INT , @NON time(0) , @PROD ti
DECLARE
@Offset INT ,
@Start DATETIME ,
@Loc INT ,
@NON time(0) ,
@PROD time(0) ,
@TOTAL TIME(0)
SET @Offset = 4
SET @Start = dateadd(day, datediff(day, 0, getdate()), -@Offset)
--SUM OF ALL DEPT CATEGORIES WORKED FOR SELECTED DATE RANGE
select Codes = (DeptCode + ' ' + Opcode)
, TimeSum = right(convert(varchar(9),(sum(datediff(second,StartTime,FinishTime)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,StartTime,FinishTime)) / 60) % 60 ),2)
, Units = sum(units)
FROM TimeLogNEW
where EventDate = @Start and Location = 10 and ID = 2372013
group by EventDate, id, DeptCode, OpCode
--SUM OF NON PRODUCTIVE HOURS WORKED (HAVING A UNITS SUM OF '0' IS CONSIDERED NON PRODUCTIVE) --NOT INCLUDING 'LL' (WHICH IS A LUNCH PERIOD)
set @NON =
(select NonProd = right(convert(varchar(9),(sum(datediff(second,'0:00:00',TimeSum)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,'0:00:00',TimeSum)) / 60) % 60 ),2)
from (select
TimeSum = right(convert(varchar(9),(sum(datediff(second,m.StartTime,m.FinishTime)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,m.StartTime,m.FinishTime)) / 60) % 60 ),2)
,Units = sum(m.units)
FROM TimeLogNEW m
where m.EventDate = @Start and opCode Not in ('ll') and m.Location = 10 and m.ID = 2372013
group by m.EventDate, m.id, m.DeptCode, m.OpCode
)t Group By Units Having Units = 0)
select @NON as 'NON-PROD_Hours'
--SUM OF PRODUCTIVE HOURS WORKED (HAVING A UNITS SUM OF MORE THAN '0' IS CONSIDERED PRODUCTIVE) --NOT INCLUDING 'LL' (WHICH IS A LUNCH PERIOD)
set @PROD =
(select TotalProd = right(convert(varchar(9),(sum(datediff(second,'0:00:00',TimeSum)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,'0:00:00',TimeSum)) / 60) % 60 ),2)
from (select
TimeSum = right(convert(varchar(9),(sum(datediff(second,m.StartTime,m.FinishTime)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,m.StartTime,m.FinishTime)) / 60) % 60 ),2)
,Units = sum(m.units)
FROM TimeLogNEW m
where m.EventDate = @Start and opCode Not in ('ll') and m.Location = 10 and m.ID = 2372013
group by m.EventDate, m.id, m.DeptCode, m.OpCode
)t Group By Units Having Units >0 )
select @PROD as 'PROD_Hours'
--SUM OF ALL HOURS WORKED --NOT INCLUDING 'LL' (WHICH IS A LUNCH PERIOD)
set @TOTAL =
(select
TotalTime_NoLunch = right(convert(varchar(9),(sum(datediff(second,StartTime,FinishTime)) / 3600 )),3) + ':' + right('0' + convert(varchar(2),(sum(datediff(second,StartTime,FinishTime)) / 60) % 60 ),2)
FROM TimeLogNEW
where EventDate = @Start and ID = 2372013 and OpCode not in ('ll'))
select @TOTAL as 'SUM_Hours'
--PERCENTAGE OF PRODUCTIVITY
select
[Prod%] =convert(varchar(30),(100 *datediff(minute,'0:00:00',@PROD)/datediff(minute,'0:00:00',@TOTAL) )) +'%'
--PERCENTAGE OF NON-PRODUCTIVITY
select
[NON Prod%] =convert(varchar(30),(100 *datediff(minute,'0:00:00',@NON)/datediff(minute,'0:00:00',@TOTAL) )) +'%'
结果显示。7-2-18
如果超过1个部门类别代码的单位数大于0,则子查询将失败。我一直在尝试重新安排查询,以允许对等于0的和和大于0的和进行分组,但我在这里遇到了难题。在子列表中解组“单位”列时,我没有得到正确的结果
下面是一个以上生产操作的原始数据。7-3-18
问题在于,您可以按DeptCode和操作码分组,但不能对这些分组的结果求和。试试这个:
DECLARE
@Offset INT ,
@Start DATETIME ,
@Loc INT = 10 ,
@NON INT ,
@PROD INT ,
@TOTAL INT
SET @Offset = 4;
SET @Start = DATEADD(day, DATEDIFF(day, 0, GETDATE()), -@Offset);
--SUM OF ALL DEPT CATEGORIES WORKED FOR SELECTED DATE RANGE
WITH
TimeLog (EventDate, [Location], ID, DeptCode, OpCode, Units, Seconds) AS (
SELECT EventDate, [Location], ID, DeptCode, OpCode, SUM(Units)
, SUM(DATEDIFF(second, StartTime, FinishTime))
FROM TimeLogNEW
GROUP BY EventDate, [Location], ID, DeptCode, OpCode
)
SELECT
Codes = (DeptCode + ' ' + Opcode)
, TimeSum = CAST(DATEADD(second, Seconds, 0) AS time(0))
, Units
FROM TimeLog
WHERE EventDate = @Start AND [Location] = @Loc AND ID = 2372013;
WITH
TimeLog (EventDate, [Location], ID, DeptCode, OpCode, Units, Seconds) AS (
SELECT EventDate, [Location], ID, DeptCode, OpCode, SUM(Units)
, SUM(DATEDIFF(second, StartTime, FinishTime))
FROM TimeLogNEW
GROUP BY EventDate, [Location], ID, DeptCode, OpCode
),
TimeSplit (EventDate, Loc, ID, DC, OC, Units, Seconds, NON_PROD, PROD) AS (
SELECT EventDate, [Location], ID, DeptCode, OpCode, Units, Seconds
, CASE WHEN Units = 0 THEN Seconds ELSE 0 END
, CASE WHEN Units > 0 THEN Seconds ELSE 0 END
FROM TimeLog
)
SELECT @NON = SUM(NON_PROD), @PROD = SUM(PROD), @TOTAL = SUM(Seconds)
FROM TimeSplit
WHERE EventDate = @Start AND Loc = @Loc AND ID = 2372013 AND OC NOT IN ('LL');
-- RESULTS
SELECT
CONVERT(nvarchar(30), @NON/3600) + RIGHT(CONVERT(nvarchar(8), DATEADD(second, @NON, 0), 108), 6) AS 'NON-PROD_Hours',
CONVERT(nvarchar(30), @PROD/3600) + RIGHT(CONVERT(nvarchar(8), DATEADD(second, @PROD, 0), 108), 6) AS 'PROD_Hours',
CONVERT(nvarchar(30), @TOTAL/3600) + RIGHT(CONVERT(nvarchar(8), DATEADD(second, @TOTAL, 0), 108), 6) AS 'SUM_Hours',
CAST(100.0 * @PROD / @TOTAL AS varchar(30)) +'%' AS 'Prod%',
CAST(100.0 * @NON / @TOTAL AS varchar(30)) +'%' AS 'NON Prod%';
按m.EventDate、m.id、m.DeptCode、m.OpCode删除组。如果多个行位于多个部门,并且您只需要这些组的总数,那么这就是导致多行发生的原因unnecessary@indiri这是结果,我在上面添加了一张图片,删除了这些组。我尝试过这个,但它没有返回正确的数据。这显示Prod%为100%。不正确,将组替换为具有“按位置”的单元。此外,由于WHERE子句将记录限制为只有一个EventDate和一个ID,因此可以删除这些列上的分组。我进一步建议不要来回转换。只需添加并保存分钟数,仅在需要时转换为varchar。试试像CONVERTvarchar8、DATEADDMinute、@TotalMinutes、0、108这样的方法。@WolfgangK谢谢,但我也尝试过这种方法,但我没有得到我想要的。我正在添加一个屏幕截图,显示我正在查询的原始数据。这可能有助于找到问题的解决方案。这很好,正是我想要的。感谢@Wolfgangkw如果总和大于24小时,“非生产小时”、“生产小时”和“总和小时”会发生什么情况?我想这就是我在原始查询中以不同方式计算时间总和的原因。@DruidUID当总和>=24小时86400秒时,在最后一个SELECT语句中从秒到时间的转换确实会失败。您可以改为转换为datetime并使用特殊类型的格式。其他一切,以及百分比计算,都将起作用。@DruidUID例如:CONVERTnvarchar30、@TOTAL/3600+RIGHTCONVERTnvarchar8、DATEADDsecond、@TOTAL、0、108、,6@DRUIDRUID,我调整了我的答案,以向您展示如何解决时间溢出问题。