Sql server 向后调度以排除假期

Sql server 向后调度以排除假期,sql-server,tsql,Sql Server,Tsql,我的系统中有反向调度。我使用了下面显示的函数来排除周末,或者将日期推回到星期五(如果在周末安排倒排),但是如何排除假期呢?。例如,我想把任何日期推到2017年11月23日和24日,在假期或28日之后 这是我用来跳过周末的代码 Create function [dbo].[PreviousWorkDay]( @date date ) returns date as begin set @date = dateadd( day, -1, @date ) return ( sele

我的系统中有反向调度。我使用了下面显示的函数来排除周末,或者将日期推回到星期五(如果在周末安排倒排),但是如何排除假期呢?。例如,我想把任何日期推到2017年11月23日和24日,在假期或28日之后

这是我用来跳过周末的代码

Create function [dbo].[PreviousWorkDay]( @date date ) returns date as
begin
  set @date = dateadd( day, -1, @date )
  return
  (
    select case datepart( weekday, @date )
      when 7 then dateadd( day, -1, @date )
      when 1 then dateadd( day, -2, @date )
      else @date
    end
  )
end 

为了实现这一点,你必须做几件事

1) 创建基础设施,列出哪些日期被视为假日。这是必要的,原因有两个:A)一些假日每年都会移动几天(例如感恩节);B)哪些假日不是工作日取决于组织

2) 正如HABO所说,消除对
datepart
/
weekday
的依赖,因为有人可能会在您的实例上更改此设置,而您现有的逻辑将陷入混乱

假日基础设施

create table dbo.holidays
    (
        holiday_dt date not null
    )

insert into dbo.holidays
values ('2017-11-23') --Thanksgiving (moves every year)
    , ('2017-12-25') --Christmas (same day every year)
回答

create function [dbo].[PreviousWorkDay]( @date date ) returns date as
begin

    declare @date_rng int = 7 --dont think there would ever be 7 holiday/weekend days in a row
        , @ans date;

    with date_list as
        (
            --use a Recursive CTE to generate a list of recent dates (assuming there is no table w/ each calendar day listed)
            select dateadd(d, -1*@date_rng, @date) as dt
            union all
            select dateadd(d,1,dt) as dt
            from date_list
            where 1=1
            and dt < @date
        )
    select @ans = max(sub.dt)
    from (
        select dl.dt
        , case when datename(dw, dl.dt) in ('Saturday', 'Sunday') then 0
               when h.holiday_dt is not null then 0
               else 1
          end as is_work_day
        from date_list as dl
        left join dbo.holidays as h on dl.dt = h.holiday_dt
        ) as sub
    where 1=1
    and sub.is_work_day = 1

    return @ans;

end

go

将返回
2017-12-22

您将需要一张公共假日的表格,然后与工作日合并搁置:如果有人抖动,您可能会对结果感到失望。@HABO您的意思是什么
DatePart(weekday,…)
的值取决于提供的日期和
的值。@@DateFirst
。您的代码基于默认的
@@DateFirst
7
。如果有人更改了您系统上的值,或试图在具有不同设置的不同系统上使用您的代码,则可能会返回意外结果。这可能不是您关心的问题,但在您的功能中记录它可能是值得的。或者修改函数以正确处理
@@DateFirst
的不同设置。
  select dbo.PreviousWorkDay('2017-12-25')