SQL - 获取日期的工作日范围在另一个日期范围内

时间:2016-03-23 05:12:57

标签: sql-server

我有2套日期范围:

  1. @StartDate@EndDate:传递给存储过程
  2. ProjectStartDateProjectEndDate:在数据库中
  3. 目标是获取ProjectStartDateProjectEndDate介于@StartDate@EndDate之间的工作日数(公众假期被忽略)。

    示例1:

    @StartDate = 2016/03/21
    @EndDate = 2016/03/25
    
    ProjectStartDate = 2016/03/13
    ProjectEndDate = 2016/03/22
    

    因此,我需要解决的工作天数是ProjectStartDateProjectEndDate介于@StartDate@Endate之间的位置 - 在这种情况下,工作天数会是2(周一至周五)

    示例2:

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

    因此,我需要计算的工作天数是ProjectStartDateProjectEndDate介于@StartDate@Endate之间的情况 - 在这种情况下,工作天数会是4(周一至周五)

    示例3:

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

    因此,我需要计算的工作天数是ProjectStartDateProjectEndDate介于@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
    

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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