【问题标题】:DATEDIFF in Business Working Hours & Days Only仅限商务工作时间和工作日的 DATEDIFF
【发布时间】:2013-05-13 12:54:28
【问题描述】:

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

例如,一家企业在工作日的 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

【问题讨论】:

    标签: tsql datediff


    【解决方案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
    

    【讨论】:

      【解决方案2】:

      我只是对你的问题感到好奇并做了这个。

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

      它功能齐全,但我生成了日期,您可能想使用您的日程表。

      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
      

      希望对你有帮助

      【讨论】:

      • 谢谢约翰,我会去看看 :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多