2

我已经找到了许多关于在 SQL 中进行日期差异问题的答案,不包括周末和节假日。我的问题是我需要进行日期比较 - 有多少子记录的工作日期在父记录发送日期的三天内?

大多数日期差异答案都涉及日历表,我认为如果我可以构建一个返回 date+3 的子选择,我就可以解决剩下的问题。但我不知道如何返回日期+3。

所以:

CREATE TABLE calendar
(
    thedate DATETIME NOT NULL,
    isweekday SMALLINT NULL,
    isholiday SMALLINT NULL
);

和:

SELECT thedate AS fromdate, xxx AS todate
FROM calendar

我想要的是 todate 是 fromdate + 72 小时,不包括周末和节假日。在 isweekday 而不是 isholiday 的情况下执行 COUNT(*) 很简单,但执行 DATEADD() 是另一回事。

我不知道从哪里开始。

4

4 回答 4

1

编辑: 更改为将非工作日包含为有效的 fromDates。

WITH rankedDates AS
    (
        SELECT 
            thedate
            , ROW_NUMBER()
                OVER(
                    ORDER BY thedate
                    ) dateRank
        FROM 
            calendar c
        WHERE 
            c.isweekday = 1 
            AND 
            c.isholiday = 0
    )
SELECT 
    c1.fromdate
    , rd2.thedate todate
FROM
    ( 
        SELECT 
            c.thedate fromDate
            , 
                (
                    SELECT 
                        TOP 1 daterank
                    FROM 
                        rankedDates rd
                    WHERE
                        rd.thedate <= c.thedate
                    ORDER BY 
                        thedate DESC
                ) dateRank
        FROM 
            calendar c
    ) c1        
LEFT JOIN
    rankedDates rd2
    ON 
        c1.dateRank + 3 = rd2.dateRank        

您可以在日历表上放置一个日期排名列来简化这一点并避免 CTE:

CREATE TABLE
    calendar
    (
        TheDate DATETIME PRIMARY KEY
        , isweekday BIT NOT NULL
        , isHoliday BIT NOT NULL DEFAULT 0
        , dateRank INT NOT NULL
    );

然后,您将仅在非假日工作日设置 daterank 列。

于 2013-05-28T19:11:48.667 回答
1

这应该可以解决问题,将“顶部”中的数字更改为您想要包含的天数。

declare @date as datetime

set @date = '5/23/13'

select
    max(_businessDates.thedate)
from (
    select 
         top 3 _Calendar.thedate 
    from calendar _Calendar
    where _Calendar.isWeekday = 1 
         and _Calendar.isholiday = 0
         and _Calendar.thedate >= @date
    order by 
         _Calendar.thedate
) as _businessDates

对于可以前进或后退一定天数的动态版本,请尝试以下操作:

declare @date as datetime
declare @DayOffset as int

set @date = '5/28/13'
set @DayOffset = -3

select
    (case when @DayOffset >= 0 then 
            max(_businessDates.thedate) 
        else 
            min(_businessDates.thedate) 
        end)
from (
    select 
         top (abs(@DayOffset) + (case when @DayOffset >= 0 then 1 else 0 end)) _Calendar.thedate
    from calendar _Calendar
    where _Calendar.isWeekday = 1
        and _Calendar.isholiday = 0
        and ( (@DayOffset >= 0 and _Calendar.thedate >= @date)
        or  (@DayOffset < 0 and _Calendar.thedate < @date) )
    order by 
         cast(_Calendar.thedate as int) * (case when @DayOffset >=0 then 1 else -1 end)
) as _businessDates

您可以将@DayOffset 设置为正数或负数。

于 2013-05-28T19:24:11.927 回答
0

如果您需要它作为 dateAdd 查询,请尝试此操作:

SELECT 
     allDates.thedate fromDate
    ,min(nonWeekendHoliday.thedate) toDate
FROM (    
    SELECT 
        thedate
    FROM 
       calendar _calendar
) allDates
LEFT JOIN (
    SELECT 
        thedate
    FROM 
       calendar _calendar
    WHERE 
        _calendar.isweekday = 1 
        AND 
        _calendar.isholiday = 0 
) nonWeekendHoliday
    on dateadd(d,3,allDates.thedate) <= nonWeekendHoliday.thedate
where allDates.thedate between '5/20/13' and '5/31/13'
group by
     allDates.thedate
于 2013-05-28T21:05:06.483 回答
0

你只需要 DATEADD,除非我不理解你的问题。

DATEADD(DAY,3,fromdate)

编辑:我明白了,不算周末或节假日,会立即更新。

更新:看起来 Jason 搞定了,但如果您使用 SQL2012 的机会不大,这里是简单版本:

SELECT todate = thedate
       fromdate = LEAD(thedate,3) OVER (ORDER BY thedate)
FROM calendar
WHERE isweekday = 1
 AND isHoliday = 0
于 2013-05-28T19:09:36.200 回答