2016-03-23 4 views
1

У меня есть 2 Наборы для диапазонов дат:SQL - Получение рабочих дней диапазон дат в другой диапазон дат

  1. @StartDate и @EndDate: передается в хранимую процедуру
  2. ProjectStartDate и ProjectEndDate: В базе данных

цель состоит в том, чтобы получить количество рабочих дней (праздничные дни игнорируются), что ProjectStartDateProjectEndDate и падение между @StartDate и @EndDate.

Пример 1:

@StartDate = 2016/03/21 
@EndDate = 2016/03/25 

ProjectStartDate = 2016/03/13 
ProjectEndDate = 2016/03/22 

Таким образом, количество рабочих дней мне нужно работать будут где ProjectStartDate и ProjectEndDate падение beween @StartDate и @Endate - в этом случае, количество рабочих дней будет 2 (пн - пт)

Пример 2:

ProjectStartDate = 2016/03/22 
ProjectEndDate = 2016/03/29 

Таким образом, количество рабочих дней мне нужно работать НУ т есть где ProjectStartDate и ProjectEndDate падение между @StartDate и @Endate - в этом случае, количество рабочих дней будет 4 (пн - пт)

Пример 3:

ProjectStartDate = 2016/03/13 
ProjectEndDate = 2016/03/29 

Так количество рабочих дней мне нужно отработать то, где ProjectStartDate и ProjectEndDate падение между @StartDate и @Endate - в этом случае, количество рабочих дней будет 5 (пн - пт)

код я должен отработать рабочие дни выглядит следующим образом:

(DATEDIFF(dd, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) + 1) 
     -(DATEDIFF(wk, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) * 2) 
     -(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Sunday' THEN 1 ELSE 0 END) 
     -(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Saturday' THEN 1 ELSE 0 END) 

Я попытался получить результат, но он частично работает. Я знаю, что есть более простой способ сделать это:

CASE WHEN(CASE WHEN @StartDate <= ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart) 
     THEN (DATEDIFF(dd, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), @EndDate) + 1) 
     -(DATEDIFF(wk, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), @EndDate) * 2) 
     -(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Sunday' THEN 1 ELSE 0 END) 
     -(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Saturday' THEN 1 ELSE 0 END) 
     ELSE (DATEDIFF(dd, @StartDate, ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) + 1) 
     -(DATEDIFF(wk, @StartDate, ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) * 2) 
     -(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN 1 ELSE 0 END) 
     -(CASE WHEN DATENAME(dw, @StartDate) = 'Saturday' THEN 1 ELSE 0 END) END) >= 5 
     THEN 5   
     ELSE (CASE WHEN @StartDate <= ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart) 
     THEN (DATEDIFF(dd, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), @EndDate) + 1) 
     -(DATEDIFF(wk, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), @EndDate) * 2) 
     -(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Sunday' THEN 1 ELSE 0 END) 
     -(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Saturday' THEN 1 ELSE 0 END) 
     ELSE (DATEDIFF(dd, @StartDate, ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) + 1) 
     -(DATEDIFF(wk, @StartDate, ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) * 2) 
     -(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN 1 ELSE 0 END) 
     -(CASE WHEN DATENAME(dw, @StartDate) = 'Saturday' THEN 1 ELSE 0 END) END) END AS DaysCalculated 
+0

Основываясь на вашем Sql синтаксиса я удалил тег MySql. –

+0

любой шанс, что вход '@ StartDate' и' @ EndDate' будет включать Sat, Sun? – Squirrel

+0

@Squirrel, В моем случае, StartDate и EndDate всегда будут в понедельник и пятницу. – AxleWack

ответ

0

Так что я нашел ответ, похоже. Я бы предпочел найти более чистый, аккуратный способ ... но я не могу тратить больше времени на это, и это работает пока. Если у кого-то есть более чистый, опрятный вариант, пожалуйста, дайте мне знать. Благодарю.

(CASE WHEN ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart) >= @StartDate AND 
       ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd) >= @EndDate 
      THEN 
       (DATEDIFF(dd, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), @EndDate) + 1) 
       -(DATEDIFF(wk, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), @EndDate) * 2) 
       -(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Sunday' THEN 1 ELSE 0 END) 
       -(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Saturday' THEN 1 ELSE 0 END) 
      ELSE 
       (CASE WHEN ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart) >= @StartDate AND 
          ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd) <= @EndDate 
       THEN 
        (DATEDIFF(dd, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) + 1) 
        -(DATEDIFF(wk, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) * 2) 
        -(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Sunday' THEN 1 ELSE 0 END) 
        -(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Saturday' THEN 1 ELSE 0 END) 
       ELSE 
        (CASE WHEN ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart) <= @StartDate AND 
          ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd) <= @EndDate 
        THEN 
         (DATEDIFF(dd, @StartDate, ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) + 1) 
         -(DATEDIFF(wk, @StartDate, ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) * 2) 
         -(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN 1 ELSE 0 END) 
         -(CASE WHEN DATENAME(dw, @StartDate) = 'Saturday' THEN 1 ELSE 0 END) 
        ELSE 
         (CASE WHEN ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart) <= @StartDate AND 
          ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd) >= @EndDate 
         THEN 
          (DATEDIFF(dd, @StartDate, @EndDate) + 1) 
          -(DATEDIFF(wk, @StartDate, @EndDate) * 2) 
          -(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN 1 ELSE 0 END) 
          -(CASE WHEN DATENAME(dw, @StartDate) = 'Saturday' THEN 1 ELSE 0 END) 
        END) END) END) END) AS CalculatedDays 
+0

В этом случае вы можете указать количество рабочих дней (праздничные дни, на которые не рассчитаны), а не весь запрос. – AxleWack

0

Как об этом

declare @StartDate date = '2016-03-21', 
    @EndDate date = '2016-03-25' 

; with tbl (ProjectStartDate , ProjectEndDate) as 
(
    select '2016-03-13', '2016-03-22' union all 
    select '2016-03-22', '2016-03-29' union all 
    select '2016-03-13', '2016-03-29' 
) 
select *, 
    [working days] = datediff( day, 
        case when ProjectStartDate > @StartDate then ProjectStartDate else @StartDate end, 
        case when ProjectEndDate < @EndDate then ProjectEndDate else @EndDate end 
       ) + 1 
from tbl