Sql server 向后调度以排除假期
我的系统中有反向调度。我使用了下面显示的函数来排除周末,或者将日期推回到星期五(如果在周末安排倒排),但是如何排除假期呢?。例如,我想把任何日期推到2017年11月23日和24日,在假期或28日之后 这是我用来跳过周末的代码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
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')