2013-05-13 31 views
0

我想写一份报告,有点卡住:/我试图显示两个日期之间的小时和分钟,但减去非业务工作时间。DATEDIFF在业务工作时间和天只

例如,一个企业在星期一至星期五的08:00至17:00之间工作,并且呼叫在今天16:00记录,并且明天在16:00关闭,这将是24小时减去营业时间,因此将在9小时。

我还创建了一个独立的表格,除了周末和商务工作日的开始以及商务工作日结束之外,这些表格还包含多年的所有日子。但我仍然坚持找出没有非营业时间的时间。

示例数据:

Call_Initiated - Call_Ended 
10/05/2013 15:00 - 13/05/2013 13:00 

结果我想

Call_Initiated - Call_Ended - Time_To_Resolve 
10/05/2013 15:00 - 13/05/2013 13:00 - 07 

回答

0

我只是好奇,你的问题并提出这一点。

也许不是最好的脚本,但它可能会给你一些关于如何解决问题的想法。

它功能齐全,但我生成的日期,你可能想使用你的日子。

declare @callLogStart datetime = '2013-01-04 16:00' 
declare @callLogEnd datetime = '2013-01-08 09:00' 

;with dates(startDate, endDate) 
as 
(
select cast('2013-01-01 08:00' as datetime) 
     ,cast('2013-01-01 17:00' as datetime) 
union all 
select DATEADD(day,1, startDate) 
     ,DATEADD(day, 1, endDate) 
from dates 
where startDate < '2013-02-01 08:00' 
) 
,startDay 
as 
(
    select * 
      ,Datediff(hour, d.startDate, d.endDate) - DATEDIFF(hour, startDate, @callLogStart) as spent 
    from dates d 
    where @callLogStart between d.startDate and d.endDate 
) 
,endDay 
as 
(
    select * 
      ,Datediff(hour, d.startDate, d.endDate) - datediff(hour, @callLogEnd, endDate) as spent 
    from dates d 
    where @callLogEnd between d.startDate and d.endDate 
) 

select --SUM(spent) as actualTime 
     spent 
     ,startDate 
     ,endDate 
     ,mark 
from 
(
    select startDate 
      ,endDate 
      ,spent 
      ,'start' as mark 
    from startDay 
    union 
    select startDate 
      ,endDate 
      ,spent 
      ,'end' 
    from endDay 
    union 
    select s.startDate 
      ,s.endDate 
      ,-Datediff(hour, s.startDate, s.endDate) 
      ,'remove' 
    from startDay s 
    join endDay e 
     on s.startDate = e.startDate 
     and s.endDate = e.endDate 
    union 
    select startDate 
      ,endDate 
      ,Datediff(hour, startDate, endDate) 
      ,'between' 
    from dates 
    where @callLogStart < startDate 
    except 
    select startDate 
      ,endDate 
      ,Datediff(hour, startDate, endDate) 
      ,'between' 
    from dates 
    where @callLogEnd < endDate 
) x 
order by  
    case mark 
     when 'start' then 0 
     when 'between' then 1 
     when 'end' then 2 
     when 'remove' then 3 
    end 

希望它可以帮助

+0

谢谢约翰我会有一个甘德:) – 2013-05-14 07:34:43

1

这是一个稍微简单一些。只是一个单选语句。我将每一步都打入了自己的专栏,这样你就可以看到它是如何工作的。你只需要最后一列来确定小时。由于它使用日期名称,因此它依赖于语言环境,但只要您知道DATEFIRST设置为什么,就可以在一周中反复出现。

此外,这不包括假期。你必须创建你自己的假期表。我参考哪里可以将其链接到最终公式。

只需将开始日期和结束日期设置为任何想要使用的开始日期和结束日期,然后在代码中使用它,执行查找/替换并将字段名称替换为这些参数。如果您使用的是SQL Server 2008或更新版本,则可以通过将打开/关闭时间切换为时间数据类型来简化很多操作。希望这可以帮助!

declare @startDate datetime = '2013-09-05 10:45:00.000', 
     @endDate datetime = '2013-09-06 08:15:00.000', 
     @zeroDate datetime = '1900-01-01 00:00:00.000', 
     @businessOpen datetime = '1900-01-01 08:00:00.000', 
     @businessClose datetime = '1900-01-01 17:00:00.000', 
     @hoursOpen int; 

select @hoursOpen = datediff(hour, @businessOpen, @businessClose); 

select @hoursOpen as hoursOpen 
     , @endDate - @startDate as actualTimeCallOpen 
     , datediff(week, @startDate, @endDate) as wholeWeekendsCallOpen 
     , datediff(day, @startDate, @endDate) as daysCallOpen 
     , (DATEDIFF(dd, @StartDate, @EndDate)) --get days apart 
      -(DATEDIFF(wk, @StartDate, @EndDate) * 2) --subtract whole weekends from the date (*2 is for 2 days per weekend) 
       +(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN 1 ELSE 0 END) --subtract the start date if it started on sunday (thus, partial weekend) 
       -(CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END) --subtract the end date if it ends on saturday (again, partial weekend) 
      as MthruFDaysOpen 
     , datediff(hour, @startDate, @endDate) as timeHoursCallOpen 
     , datediff(minute, @businessOpen, convert(datetime, '1900-01-01 ' + convert(varchar(8),@startDate,108)))/60.0 as hoursOpenBeforeCall 
     , datediff(minute, convert(datetime, '1900-01-01 ' + convert(varchar(8), @endDate, 108)), @businessClose)/60.0 as hoursOpenAfterCall 
     , (@hoursOpen - ((datediff(minute, convert(datetime, '1900-01-01 ' + convert(varchar(8), @endDate, 108)), @businessClose) + datediff(minute, @businessOpen, convert(datetime, '1900-01-01 ' + convert(varchar(8),@startDate,108))))/60.0)) as partialHourDay 
     , (((DATEDIFF(dd, @StartDate, @EndDate)) --get days apart, 
      - (DATEDIFF(wk, @StartDate, @EndDate) * 2) --subtract whole weekends from the date 
      + (CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN 1 ELSE 0 END) --subtract the start date if it started on sunday (thus, partial weekend) 
      - (CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END) --subtract the end date if it ends on saturday (again, partial weekend) 
      --If you have a table with holidays in it, you can subtract the count of holidays from this as well 
      --test where the holiday is between startdate and end date and the holiday itself isn't a saturday or sunday 
      ) * @hoursOpen) --multiply the whole days open times hours per day, giving us 
     + (@hoursOpen --start with hours open 
      - (-- then subtract the sum of hours the business was open before and after the call 
       (datediff(minute, convert(datetime, '1900-01-01 ' + convert(varchar(8), @endDate, 108)), @businessClose) --calculate this different in minutes for greater accuracy 
        + datediff(minute, @businessOpen, convert(datetime, '1900-01-01 ' + convert(varchar(8),@startDate,108))) 
       )/60.0) --divide by 60 to convert back to hours before subtracting from @hours open 
      ) as businessTimeOpen