2013-05-13 44 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