我希望有人可以帮助我。我把简单的例子放在下面: 出于计费目的,我需要跳过假期和周末来设置结算日期的正确截止日期。 我有一个假期表,为公司保留所有假期(可能包含一些周末这样的周六 - 现在不太确定像银行这样的公司,我们现在不能考虑特殊情况)。
我需要连续周末在数据库中找出连续假期。
对于数据库中的假日数据,例如:
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
感谢您的帮助。
答案 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日是假期(如果您在假期中有阵亡将士纪念日)表)。