2013-05-13 1 views
0

보고서를 작성하려고하는데 다소 시간이 걸렸습니다./두 시간 사이의 시간과 분을 업무 시간 이외의 시간으로 표시하려고합니다.DATEDIFF 업무 시간 및 요일에만

예 비즈니스는 평일 08 시부 터 17 시까 지 작동하며 오늘 16시에 통화가 기록되고 내일 16시에 종료되어 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

감사합니다. 요한 나는 멍청 할 것입니다. :) –

1

을 도움이되기를 바랍니다. 단일 선택 문. 각 단계를 하나의 항목으로 나눠서 어떻게 작동하는지 확인할 수있었습니다. 당신은 시간을 알아 내기 위해 마지막 칼럼 만 필요합니다. 그것은 locale에 종속적인데, datename을 사용하기 때문입니다. 그러나 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