我需要编写一个存储过程,该过程给出一个日期和一些工作日,将那些给定日期添加到该日期,并返回新日期,而不计算非工作日和周末。非工作日存储在另一个表中。
这是我的第二个存储过程,所以我不太熟悉词汇,所以,如果你发现明显的错误,请提前抱歉。
到目前为止,我已经达到了这个目标:
CREATE PROCEDURE DateAdd
(@GivenDate DATE, @DaysToAdd int)
DECLARE @ReturnDate DATE,
DECLARE @Counter int,
DECLARE @NextDate DATE
AS
SET @Counter = 0
SET @ReturnDate = @GivenDate
SET @NextDate = @GivenDate
GO
WHILE (@Counter < @DaysToAdd)
@Counter + 1
IF(datepart(weekday, @FechaVariable) !=6 &&
datepart(weekday, @FechaVariable) != 7)
IF(#TODO-- call the query and check it with @NextDate)
@FechaRetorno = DateAdd(dd, 1, @FechaRetorno)
ELSE IF @NextDate = DateAdd(dd, 1, @NextDate)
EN IF
END WHILE
-- I don't know where to put this query, or how to call ir from the IF
SELECT Date
FROM non_working_days
WHERE Date = $Variable
RETURN @FechaRetorno
答案 0 :(得分:2)
Tally / Calendar表也可以使用,但您可以使用ad-hoc计数表执行此操作。此外,这种方法比递归cte更快。
一个附加选项是您可以通过在WHERE子句中添加以下内容来排除HOLIDAYS。
and D not in ('2017-12-25','2018-01-01')
SQL
Declare @Date date = '2017-04-01'
Declare @Days int = 5
Select D
From (
Select D,RN=Row_Number() over (Order by D)
From (Select Top ((@Days*2)+10) D=DateAdd(DAY,-1+Row_Number() Over (Order By Number),@Date) From master..spt_values ) A
Where DateName(WEEKDAY,D) not in ('Saturday','Sunday')
) A
Where RN=@Days
<强>返回强>
2017-04-07
答案 1 :(得分:1)
下面。假设另一个表名为OtherTable,并且要避免的日期列称为DatesToAvoid,这将一次添加一天到您的日期,如果该日期不是周末或DatesToAvoid,它将减少@DaysToAdd。一旦@DaysToAdd达到0,它就会停止。
CREATE PROCEDURE DateAddsp(@GivenDate DATE, @DaysToAdd int)
AS
BEGIN
WHILE @DaystoAdd > 0
BEGIN
SET @GivenDate = DATEADD(DAY,1,@GivenDate)
SET @DaysToAdd = CASE
WHEN @GivenDate IN (SELECT DatesToAvoid FROM OtherTable) OR DATEPART(DW,@GivenDate) IN (1,7) /* Saturday or Sunday*/
THEN @DaysToAdd
ELSE @DaysToAdd + 1
END
END
RETURN DATEADD(DW, @DaysToAdd, @GivenDate);
END
答案 2 :(得分:0)
你过于复杂。您需要使用的函数是dateadd:https://docs.microsoft.com/en-us/sql/t-sql/functions/dateadd-transact-sql
尝试以下方面的内容:
CREATE PROCEDURE DateAddsp(@GivenDate DATE, @DaysToAdd int)
AS
BEGIN
RETURN DATEADD(DW, @DaysToAdd, @GivenDate);
END
您不能使用dateadd作为存储过程的名称,因为它是SQL Server中的保留字 - 它是我刚刚在上面使用的函数的名称。
答案 3 :(得分:0)
这是一个内联表值函数,而不是一个过程,用于获取将工作日添加到日期的结果。
create function dbo.udf_add_working_days (@Date date, @Days int)
returns table with schemabinding as return (
with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, days as (
select top (1000)
[Date]=convert(date,dateadd(day,row_number() over(order by (select 1))-1,@date))
from n as deka cross join n as hecto cross join n as kilo
order by [Date]
)
, working_days as (
select top (@Days)
[Date]
from days
where datename(weekday,[date]) not in ('Saturday','Sunday')
/* -- put your non working days table info here and uncomment this clause
and not exists (
select 1
from dbo.HolidayTable h
where days.[Date] = h.HolidayDate
)
--*/
order by [Date]
)
select top 1 [date]
from working_days
order by [Date] desc
);
go
你可以这样称呼它:
select [date]
from dbo.udf_add_working_days('20170401',10)
rextester演示:http://rextester.com/ITXB6884
返回:
+------------+
| date |
+------------+
| 2017-04-14 |
+------------+
或者您可以使用cross apply()
select ...
, x.Date as NewWorkDate
from t
dbo.udf_add_working_days (t.[Date], t.[NumberOfDays]) as x
对内联表值函数的引用