2014-08-27 2 views
0

У меня есть набор данных, основанный на отметках времени, то есть startdate, enddate. Я хотел бы рассчитать количество рабочих часов между отметками времени, например, для типичной (M-F, 8-5) недели.Суммирование между временными отметками

Например, если билет пришел в 8:00 утра в понедельник и был закрыт 9:00 утра, я бы хотел, чтобы заявление показывало 10 часов. Мне также нужно пропустить выходные дни из расчета. Может ли кто-нибудь рекомендовать подход к решению для этого? Благодарим вас за помощь.

+0

Я предлагаю вычесть последнюю дату из первого и преобразовать в часы/минуты, а логику «CASE» - обрабатывать нерабочие часы. –

ответ

0

В качестве примера (без наличия вашей структуры таблицы передо мной), вот что я придумал, основываясь на другом ответе, который я сделал для generating rows for time.

declare @datetimes table (id int primary key identity(1,1), startdatetime datetime, enddatetime datetime) 
insert into @datetimes (startdatetime,enddatetime) values 
     ('2014-08-26 08:00:00','2014-08-27 09:00:00') 
    , ('2014-07-16 08:00:00','2014-07-28 09:00:00') 

declare @defaultDayStart time = '08:00:00', @defaultDayEnd time = '17:00:00' 

select T.ID, sum(Z.ShadowHours) 
from (
     select id, startdatetime, enddatetime, datediff(hh,startdatetime,enddatetime) TotalTime 
     from @datetimes 
    ) T 
    CROSS APPLY (
      SELECT 
       RowID-1 AS ShadowDays 
       , CASE 
        WHEN DATENAME(dw,DATEADD(dd, RowID - 1,t.startdatetime)) IN ('Saturday', 'Sunday') THEN 0 
        ELSE DATEDIFF(hh, CASE RowID WHEN MIN(RowID)OVER(PARTITION BY t.id) THEN t.startdatetime ELSE CONVERT(DATETIME,CONVERT(DATE, DATEADD(dd, RowID - 1,t.startdatetime))) + @defaultDayStart END 
          , CASE RowID WHEN MAX(RowID)OVER(PARTITION BY t.id) THEN t.enddatetime ELSE CONVERT(DATETIME,CONVERT(DATE, DATEADD(dd, RowID - 1,t.startdatetime))) + @defaultDayEnd END 
          ) 
       END AS ShadowHours 
       , DATENAME(dw,DATEADD(dd, RowID - 1,t.startdatetime)) wd 
      FROM (
       SELECT ROW_NUMBER()OVER(ORDER BY S.NAME) AS RowID 
       FROM master..spt_values S 
       ) X 
      WHERE DATEDIFF(dd,startdatetime,enddatetime) + 1 >= RowID 
     ) Z 
GROUP BY T.id 

Этот пример является рудиментарным и не использует таблицу календаря, содержащую, например, праздники. Это также не делает расчеты в отношении обеденных перерывов, которые должны быть там, так как большинство мест считают незаконным не предоставлять перерыв на обед в течение 8-часовых рабочих дней. Это соображения, которые вы, скорее всего, попросите адаптировать для этого. Измените свой вопрос и оставьте мне комментарий, если вы хотите помочь в этой сфере.

Смежные вопросы