从多行收集的经过时间总和

时间:2018-07-06 20:24:08

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

我试图根据他们一天中执行的工作类型来显示团队的生产率与非生产率的百分比。我可以使用下面的代码成功实现所需的格式,但是如果某位员工在1天之内在2个单独的部门中都有工作,则子查询将失败,因为它返回了多行。

这就是我现在正在使用的

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

enter image description here

如果多个部门类别codes中有1个大于0 Units,则子查询失败。我一直在尝试重新安排查询,以允许将等于0的总和和大于0的总和分组,但是在这里被卡住了。将子集中的Units列取消分组时,没有得到正确的结果。

这是经过多次生产操作后原始数据的样子。 7-3-18 enter image description here

1 个答案:

答案 0 :(得分:1)

问题是您按DeptCode和OpCode分组,但没有对这些结果求和。试试这个:

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%';