在表格中计算连续的假期/周末

时间:2014-05-23 13:51:02

标签: sql sql-server

我希望有人可以帮助我。我把简单的例子放在下面: 出于计费目的,我需要跳过假期和周末来设置结算日期的正确截止日期。 我有一个假期表,为公司保留所有假期(可能包含一些周末这样的周六 - 现在不太确定像银行这样的公司,我们现在不能考虑特殊情况)。

我需要连续周末在数据库中找出连续假期。

对于数据库中的假日数据,例如:

 EXCP_DATE ID 
 ----------- ---------- -------------------- ---------- 
 3/29/2013 1 
 4/1/2013 1 
 12/9/2013 1 
 12/10/2013 1 
 12/25/2013 1 
 12/26/2013 1 
 12/27/2013 1 
 12/28/2013 1 

我需要假期和周末的数量"出现"柱。连续假期/周末 我的CONSECUTIVE_DAY:1表示日期连续假期/周末

 ID EXCP_DATE WeekDay CONSECUTIVE_DAY OCCURENCES
 1 3/29/2013 FRIDAY 1 3 
 2 4/1/2013 MONDAY 0 1 
 3 12/9/2013 MONDAY 1 2 
 4 12/10/2013 TUESDAY 0 1 
 5 12/25/2013 WEDNESDAY 1 5 
 6 12/26/2013 THURSDAY 1 4 
 7 12/27/2013 FRIDAY 1 3 
 8 12/28/2013 SATURDAY 1 2 

以下是适用于大多数情况的查询。它只有在连续假期超过2个时才会失败,因为它只会导致一步。

SELECT A.*
    ,CASE 
        WHEN CONSECUTIVE_DAY = 1
            THEN CASE 
                    WHEN upper(datename(weekday, EXCP_DATE)) = 'FRIDAY'
                        AND LEAD(EXCP_DATE) OVER (
                            ORDER BY EXCP_DATE
                            ) = (EXCP_DATE + 3)
                        THEN DATEdiff(dd, EXCP_DATE, LEAD(EXCP_DATE) OVER (
                                    ORDER BY EXCP_DATE
                                    )) + 1
                    WHEN upper(datename(weekday, EXCP_DATE)) = 'FRIDAY'
                        AND LEAD(EXCP_DATE) OVER (
                            ORDER BY EXCP_DATE
                            ) <> (EXCP_DATE + 3)
                        THEN 3
                    ELSE DATEdiff(dd, EXCP_DATE, LEAD(EXCP_DATE) OVER (
                                ORDER BY EXCP_DATE
                                )) + 1
                    END
        ELSE CONSECUTIVE_DAY
        END OCCURENCES
FROM (
    SELECT T.*
        ,upper(datename(weekday, EXCP_DATE)) WeekDay
        ,Lead(EXCP_DATE, 1, EXCP_DATE) OVER (
            ORDER BY EXCP_DATE
            ) Lead
        ,EXCP_DATE + 1 [EXCP_DATE + 1]
        ,EXCP_DATE + 3 [EXCP_DATE +3]
        ,datename(weekday, EXCP_DATE + 3) [DateName_EXCP_DATE +3]
        ,
        ---------------------------
        CASE 
            WHEN Lead(EXCP_DATE, 1, EXCP_DATE) OVER (
                    ORDER BY EXCP_DATE
                    ) = EXCP_DATE + 1
                THEN 1
            WHEN upper(datename(weekday, EXCP_DATE)) = 'FRIDAY'
                AND LEAD(EXCP_DATE) OVER (
                    ORDER BY EXCP_DATE
                    ) = EXCP_DATE + 3
                THEN 1
            WHEN upper(datename(weekday, EXCP_DATE)) = 'SATURDAY'
                AND LEAD(EXCP_DATE) OVER (
                    ORDER BY EXCP_DATE
                    ) = EXCP_DATE + 2
                THEN 1
            ELSE 0
            END CONSECUTIVE_DAY
    FROM TEST1 T
    ) A

-----------------------------------数字5和6不正确。如何递归Lead?

结果:

 ID EXCP_DATE WeekDay Lead EXCP_DATE + 1 EXCP_DATE +3 DateName_EXCP_DATE +3 CONSECUTIVE_DAY OCCURENCES
 1 3/29/2013 FRIDAY 4/1/2013 3/30/2013 4/1/2013 Monday 1 4
 2 4/1/2013 MONDAY 12/9/2013 4/2/2013 4/4/2013 Thursday 0 0
 3 12/9/2013 MONDAY 12/10/2013 12/10/2013 12/12/2013 Thursday 1 2
 4 12/10/2013 TUESDAY 12/25/2013 12/11/2013 12/13/2013 Friday 0 0
 5 12/25/2013 WEDNESDAY 12/26/2013 12/26/2013 12/28/2013 Saturday 1 2
 6 12/26/2013 THURSDAY 12/27/2013 12/27/2013 12/29/2013 Sunday 1 2
 8 12/27/2013 FRIDAY 12/28/2013 12/28/2013 12/30/2013 Monday 1 3
 7 12/28/2013 SATURDAY 12/28/2013 12/29/2013 12/31/2013 Tuesday 0 0

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

我会使用不同的方法。创建一个只在提供开始日期时返回下一个有效营业日期的函数。

例如,假设某人的截止日期是2014年5月24日(星期六)计算的。您可以将该值传递给函数以返回下一个有效的业务日期。这是我写的一个快速功能。

此功能假设您有一个名为[Holidays]的表格,其中包含贵公司假期的日期。

CREATE FUNCTION [dbo].[NextBusinessDay]
(
    @BusinessDay DATE
)
RETURNS DATE AS
BEGIN
    DECLARE @GoodDay DATE;
    WITH cte AS (
        SELECT @BusinessDay AS good_date
        UNION ALL
        SELECT DateAdd(d,1,good_date)
        FROM CTE 
        WHERE good_date < DateAdd(d,7,@BusinessDay)
    )
    SELECT @GoodDay = min(good_date) FROM cte
    WHERE Upper(DateName(WEEKDAY, good_date)) NOT IN ('SATURDAY','SUNDAY')
    AND NOT EXISTS (SELECT [Holiday] FROM [Holidays] WHERE [Holiday] = good_date);
    RETURN @GoodDay;
END;

然后你只需传递日期。

SELECT DueDate, [dbo].[NextBusinessDay](DueDate) FROM Whatever

在上面的示例中,这将返回2014年5月27日,因为2014年5月24日和5/25/2014是周末,2014年5月26日是假期(如果您在假期中有阵亡将士纪念日)表)。