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,我调整了我的答案,以向您展示如何解决时间溢出问题。