SQL Server存储过程将日期添加到日期

时间:2017-04-06 17:34:05

标签: sql-server stored-procedures

我需要编写一个存储过程,该过程给出一个日期和一些工作日,将那些给定日期添加到该日期,并返回新日期,而不计算非工作日和周末。非工作日存储在另一个表中。

这是我的第二个存储过程,所以我不太熟悉词汇,所以,如果你发现明显的错误,请提前抱歉。

到目前为止,我已经达到了这个目标:

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

4 个答案:

答案 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

对内联表值函数的引用