2017-04-06 123 views
2

我需要編寫一個存儲過程,給定日期和工作日數,將給定日期添加到該日期並返回新日期,工作日和週末。非工作日存儲在另一個表中。SQL Server存儲過程將日期添加到日期

這是我的第二個存儲過程,所以我對lexic不太熟悉,所以,如果您發現明顯的錯誤,請提前抱歉。

到目前爲止,我已經得到了這一點:

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

[壞習慣踢:使用帶有日期/時間操作速記 - 亞倫貝特朗(http://sqlblog.com/blogs/aaron_b ertrand/archive/2011/09/20/bad-habit-to-kick-using-short-with-date-time-operations.aspx) – SqlZim

回答

2

一個理貨/日曆表也可以做到這一點,但您可以通過一個專門的理貨表來做到這一點。而且,這種方法比遞歸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 [email protected] 

返回

2017-04-07 
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 - 它是我剛剛使用過的函數的名稱。

+0

感謝您的回覆,我使用DATEADD,但我需要每天但是週末的帳戶,以及我在另一張桌子上的幾個日期。 –

+0

您可以發佈該表格中的示例數據嗎? – Eli

+0

該表格包含一列日期。沒有其他的。 –

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

內聯表參照值函數