SQL - WHERE子句在下一个工作日返回结果

时间:2009-08-18 11:58:46

标签: sql tsql reporting-services

我现在似乎在问很多SQL问题。 (我通常会编写一个程序来将数据排序到报表中,但是目前这是不可能的,需要使用SQL来完成)

问题 我需要一个where子句,它在下一个工作日返回结果。即01/01/01周一,下一个工作日是02/01/01周二,这可以通过简单的日期添加来实现。但是在05/01/01星期五,下一个工作日是星期一08/01/01。有没有内置的东西可以帮助解决这个问题?

感谢您的建议。

9 个答案:

答案 0 :(得分:4)

关键是使用DATEPART(weekday,@date)功能,它会返回星期几,所以如果是星期六或星期日你只需要在当前日期添加一两个来获得所需的结果。

您可以轻松创建用户定义的函数,例如Pinal Dave具有此

CREATE FUNCTION dbo.udf_GetPrevNextWorkDay (@dtDate DATETIME, @strPrevNext VARCHAR(10))
RETURNS DATETIME
AS
BEGIN
DECLARE @intDay INT
DECLARE @rtResult DATETIME
SET @intDay = DATEPART(weekday,@dtDate)
--To find Previous working day
IF @strPrevNext = 'Previous'
IF @intDay = 1
SET @rtResult = DATEADD(d,-2,@dtDate)
ELSE
IF @intDay = 2
SET @rtResult = DATEADD(d,-3,@dtDate)
ELSE
SET @rtResult = DATEADD(d,-1,@dtDate)
--To find Next working day
ELSE
IF @strPrevNext = 'Next'
IF @intDay = 6
SET @rtResult = DATEADD(d,3,@dtDate)
ELSE
IF @intDay = 7
SET @rtResult = DATEADD(d,2,@dtDate)
ELSE
SET @rtResult = DATEADD(d,1,@dtDate)
--Default case returns date passed to function
ELSE
SET @rtResult = @dtDate
RETURN @rtResult
END
GO

答案 1 :(得分:3)

CREATE FUNCTION dbo.uf_GetNextWorkingDay (@givenDate DATETIME)
RETURNS DATETIME
AS
BEGIN

    DECLARE @workingDate DATETIME

    IF (DATENAME(dw , @givenDate) = 'Friday')
        BEGIN
             SET @workingDate = DATEADD(day, 3, @givenDate)
        END
    ELSE IF (DATENAME(dw , @givenDate) = 'Saturday')
        BEGIN
             SET @workingDate = DATEADD(day, 2, @givenDate)
        END
    ELSE 
        BEGIN
             SET @workingDate = DATEADD(day, 1, @givenDate)
        END

    RETURN @workingDate
END

一篇好文章http://ryanfarley.com/blog/archive/2005/02/14/1685.aspx

答案 2 :(得分:2)

你可以通过一个简单的日期检查来做到这一点,并添加3天而不是一个星期五。但是,您是否需要考虑公众假期?

答案 3 :(得分:1)

对Cashif的所有信用 - 我修改了他以包括一个非常轻量级的假日表(tblHolidays和一个日期字段HolDate) - 如果你足够幸运的话,每年约10行要休息很多天!

我的版本返回date类型(我觉得更容易使用)。我也经历过不止一次 - 如果星期四是你的开始日而星期五是假期,你必须再增加2天才能到达星期一(或下一个工作日)。然后检查以确保下周不以假期开始。

CREATE FUNCTION [dbo].[GetNextWorkingDay] (@givenDate DATE)
RETURNS DATE
AS
BEGIN
    DECLARE @workingDate DATETIME
    IF (DATENAME(dw , @givenDate) = 'Friday')
    BEGIN
         SET @workingDate = DATEADD(day, 3, @givenDate)
    END
    ELSE IF (DATENAME(dw , @givenDate) = 'Saturday')
    BEGIN
         SET @workingDate = DATEADD(day, 2, @givenDate)
    END
    ELSE 
    BEGIN
         SET @workingDate = DATEADD(day, 1, @givenDate)
    END

    while ((Select  count(*) from tblHolidays where holdate = @workingDate) > 0)
    begin
        set @workingDate = dateadd(dd,1,@WorkingDate)
    end
    -- if adding a day makes it a Saturday, add 2 more to get to Monday (and test to make sure the week doesn't start with a holiday)
    IF (DATENAME(dw , @workingDate) = 'Saturday')
    BEGIN
         SET @workingDate = DATEADD(day, 2, @workingDate)
    END


    while ((Select  count(*) from tblHolidays where holdate = @workingDate) > 0)
    begin
        set @workingDate = dateadd(dd,1,@WorkingDate)
    end
    RETURN @workingDate
END

...当然你应该重构,所以代码不会重复,并且包含一个while子句,只需要重复多次就可以到达一个工作日,但我有一个截止日期......这将是另一个不那么忙碌的一天。

答案 4 :(得分:1)

这是我为一次性申请所做的事情:

        WHILE EXISTS (SELECT * FROM Holidays WHERE CONVERT(VARCHAR, HolidayDate,101) = CONVERT(VARCHAR,@DateVariable 101 ) OR DATENAME(WEEKDAY, @DateVariable)='SATURDAY' OR DATENAME(WEEKDAY, @DateVariable)='SUNDAY')
        BEGIN
            SET @DateVariable = DateAdd(day,1,@DateVariable)
            PRINT @DateVariable -- If you want
        END

请注意,我们的Holidays表存储过去和未来年份的所有假期。

答案 5 :(得分:0)

您可以使用简单的case语句执行此操作。

select case when datepart(dw, getdate()) >= 6 then getdate() + (9 - datepart(dw, getdate())) else getdate() + 1 end

答案 6 :(得分:0)

您需要的是日历表。如果您需要考虑周末以外的假期,那么下一个工作日并不是那么简单。该表基本上只包含两列Date和一个整数字段,表示它是否是工作/非工作日 - 但也可以有其他列 - 例如季度等。

此表每年填充一次,然后根据需要进行维护。获得下一个工作日的结果就像这样的查询一样简单。

SELECT field1,filed2 from your table T where your date_Field = (SELECT min(date) From calendar table where WorkingDay = 1 and date > GetDate())

/ P

答案 7 :(得分:0)

这样的事情怎么样?

select * from table
where (date = dateadd(dd,1,@today) and datepart(weekday,@today) not in (6,0) ) --its not friday or saturday 
or    (date = dateadd(dd,2,@today) and datepart(weekday,@today) = 0) -- its saturday 
or    (date = dateadd(dd,3,@today) and datepart(weekday,@today) = 6) --its friday

日期属性应与@today具有相同的时间,否则您还必须在

之间使用

答案 8 :(得分:0)

上面已经基本回答了,但我花了一段时间才得到它,我想也许这会对某人有所帮助。使用简单的CASE-WHEN。

这是一项检查,以便找出哪些天是工作日

DATEPART(dw, date) -> MON through FRI = 1,2,3,4,5    SAT = 6,     SUN = 7

这是CASE-WHEN:

CASE
    WHEN DATEPART(weekday, date) <= 5 THEN date       -- weekdays, no change
    WHEN DATEPART(weekday, date)  = 6 THEN date + 2   -- SAT + 2 = MON
    WHEN DATEPART(weekday, date)  = 6 THEN date + 1   -- SUN + 1 = MON
END AS 'WEEKDAY_DATES'

检查,如果该声明实际上仅为您提供工作日:

CASE
    WHEN DATEPART(weekday, date) <= 5 THEN DATENAME(weekday, date)
    WHEN DATEPART(weekday, date)  = 6 THEN DATENAME(weekday, date + 2)
    WHEN DATEPART(weekday, date)  = 6 THEN DATENAME(weekday, date + 1)
END AS 'WEEKDAY_NAMES'