获取下一个工作日期

时间:2014-07-09 11:23:12

标签: sql sql-server tsql

嗨,我有这个函数应该返回下一个工作日期:

ALTER FUNCTION [dbo].[BusDaysDateAdd] 
(
   @FromDate datetime,
   @DaysToAdd int
)
RETURNS datetime
AS
BEGIN
   DECLARE @Result datetime

   SET @Result = DATEADD(day, (@DaysToAdd % 5) + CASE ((@@DATEFIRST + DATEPART(weekday, @FromDate) + (@DaysToAdd % 5)) % 7)
                                                 WHEN 0 THEN 2
                                                 WHEN 1 THEN 1
                                                 ELSE 0 END, DATEADD(week, (@DaysToAdd / 5), @FromDate))

   RETURN @Result
END

    Set DATEFIRST 1

Select

    'Today'
    ,DATENAME(WEEKDAY,dbo.BusDaysDateAdd(getdate(),1))
    ,DATENAME(WEEKDAY,dbo.BusDaysDateAdd(getdate(),2))
    ,DATENAME(WEEKDAY,dbo.BusDaysDateAdd(getdate(),3))
    ,DATENAME(WEEKDAY,dbo.BusDaysDateAdd(getdate(),4))
    ,DATENAME(WEEKDAY,dbo.BusDaysDateAdd(getdate(),5))
    ,dbo.BusDaysDateAdd(getdate(),3)
    ,dbo.BusDaysDateAdd(getdate(),4)
    ,dbo.BusDaysDateAdd(getdate(),5)

问题是,如果想要增加4天,它会在星期一返回,但它应该在星期二返回。

有人能指出问题出在我的代码的哪个位置吗?

4 个答案:

答案 0 :(得分:0)

尝试像这样修改你的功能

ALTER FUNCTION [dbo].[BusDaysDateAdd] 
(
   @FromDate datetime,
   @DaysToAdd int
)
RETURNS datetime
AS
BEGIN
   DECLARE @Result datetime

   SET @Result = DATEADD(day, (@DaysToAdd % 5) + CASE ((@@DATEFIRST + DATEPART(weekday, @FromDate) + (@DaysToAdd % 5)) % 7)
                                                 WHEN 0 THEN 2
                                                 WHEN 1 THEN 2
                                                 ELSE 0 END, DATEADD(week, (@DaysToAdd / 5), @FromDate))

   RETURN @Result
END

答案 1 :(得分:0)

试试这个:

SET @Result = DATEADD(day, 
                      @DaysToAdd + 
                        CASE DATEPART(weekday, DATEADD(day, @DaysToAdd,@fromdate))
                             WHEN 6 THEN 2
                             WHEN 7 THEN 1
                        ELSE 0 END, 
                      @FromDate)

答案 2 :(得分:0)

DECLARE @InDate DATE = '2014-07-17'
DECLARE @number_of_numbers INT = 100000;
DECLARE @MaxBusDays INT = 24

这部分只是设置日期,数字表的最大大小以及我想要添加的工作日数

;WITH
    a AS (SELECT 1 AS i UNION ALL SELECT 1),
    b AS (SELECT 1 AS i FROM a AS x, a AS y),
    c AS (SELECT 1 AS i FROM b AS x, b AS y),
    d AS (SELECT 1 AS i FROM c AS x, c AS y),
    e AS (SELECT 1 AS i FROM d AS x, d AS y),
    f AS (SELECT 1 AS i FROM e AS x, e AS y),
    numbers AS 
(
    SELECT TOP(@number_of_numbers)
    ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS number
    FROM f
)

上面这一部分只是为了获取日期而设置了一个包含100000个数字的数字表。

 SELECT
    @InDate StartDate,
    DATENAME(DW, @InDate) StartName, 
    @MaxBusDays DaysToAdd,
    d.* 
 FROM
 (
    SELECT 
        DATEADD(DAY, +number, @InDate) CheckDate, 
        DATENAME(DW, DATEADD(DAY, +number, @InDate)) CheckName, 
        ROW_NUMBER() OVER (ORDER BY DATEADD(DAY, +number, @InDate)) MaxRow
    FROM Numbers
    WHERE DATENAME(DW, DATEADD(DAY, +number, @InDate)) NOT IN ('Saturday','Sunday')
) d
WHERE d.MaxRow = @MaxBusDays

我加入数字表并创建一系列日期(不包括周末),然后我就抓住了我想要添加的工作日数。如果您使用< =它将返回所有工作日的数组,直到该数字。

答案 3 :(得分:0)

放手一搏:

ALTER FUNCTION [dbo].[BusDaysDateAdd] 
(
   @FromDate datetime,
   @DaysToAdd int
)
RETURNS datetime
AS
BEGIN
   DECLARE @Result datetime

   SET @Result = 
    DATEADD(day, 
        @DaysToAdd + 
        CASE 
            WHEN DATEPART(weekday, @FromDate) = 2 AND @DaysToAdd > 4 THEN 2 --Mon
            WHEN DATEPART(weekday, @FromDate) = 3 AND @DaysToAdd > 3 THEN 2 --Tue
            WHEN DATEPART(weekday, @FromDate) = 4 AND @DaysToAdd > 2 THEN 2 --Wed
            WHEN DATEPART(weekday, @FromDate) = 5 AND @DaysToAdd > 1 THEN 2 --Thu
            WHEN DATEPART(weekday, @FromDate) = 6 AND @DaysToAdd > 0 THEN 2 --Fri
            WHEN DATEPART(weekday, @FromDate) = 7 THEN 2 --Sat
            WHEN DATEPART(weekday, @FromDate) = 1 THEN 1 --Sun
            ELSE 0 
        END, 
    @FromDate)

   RETURN @Result
END

这不是多元文化,但它适用于跳过周末,而不是仅仅在周末放弃时增加额外的天数。