我正在创建一个调整日期和周末的日期。
示例数据:
Adjusted Date | Adjusted Date(Excluding Holidays and weekends)
02/06/16 | 02/09/16
在我的例子中,日期是一个周末,调整日期变为feb 9因为feb 8是假日,所以需要调整以使调整后的日期成为工作日。目前,我有一个财政年度所有周末和假期的分隔表。
select case when (
select count(dbo.WeekendsHoliday.[Weekends & Holidays])
from dbo.WeekendsHoliday
where dbo.WeekendsHoliday.[Weekends & Holidays]
= case when convert(time, [Time Received]) > convert(time, '5:00:00 PM')
then dateadd(day, 1, [Date Received])
else [Date Received]
end
) > 0
then case (datename(DW,
case when convert(time, [Time Received]) > convert(time, '5:00:00 PM')
then dateadd(day, 1, [Date Received])
else [Date Received]
end))
when 'Saturday'
then dateadd(day, 2,
case when convert(time, [Time Received]) > convert(time, '5:00:00 PM')
then dateadd(day, 1, [Date Received])
else [Date Received]
end)
else dateadd(day, 1,
case when convert(time, [Time Received]) > convert(time, '5:00:00 PM')
then dateadd(day, 1, [Date Received])
else [Date Received]
end)
end
end as [Adjusted Date Excluding holidays and weekends]
这里发生的事情是假期是连续2天(星期四和星期五),调整日期是星期六,因为这是一个周末仍然无效。
调整后的日期是此处的别名
我真的需要你的帮助。感谢
答案 0 :(得分:3)
这将获取您的WeekendsHoliday表中的日期,并查找不在同一个表中的第二天。
然后,如果您的表中的日期位于WeekendsHoliday表中,则您将结果连接到结果以获取“下一天”
DECLARE @WeekendsHoliday TABLE ([Weekends & Holidays] DATETIME)
INSERT INTO @WeekendsHoliday VALUES
('2016-03-05'),
('2016-03-06'),
('2016-03-07'),
('2016-03-12'),
('2016-03-13');
DECLARE @Schedule TABLE ([WorkDay] DATETIME)
INSERT INTO @Schedule VALUES
('2016-03-02'),
('2016-03-03'),
('2016-03-05'),
('2016-03-07'),
('2016-03-08'),
('2016-03-11'),
('2016-03-12');
WITH RecursiveCTE AS
(
SELECT
[Weekends & Holidays],
DATEADD(d, 1, [Weekends & Holidays]) AS [Next Day]
FROM
@WeekendsHoliday
UNION ALL
SELECT
cte.[Weekends & Holidays],
DATEADD(d, 1, [Next Day])
FROM
RecursiveCTE cte
WHERE
[Next Day] IN (SELECT [Weekends & Holidays] FROM @WeekendsHoliday)
),
AggregateCTE AS (
SELECT
[Weekends & Holidays],
MAX([Next Day]) [Next Day]
FROM
RecursiveCTE
GROUP BY
[Weekends & Holidays]
)
SELECT
s.WorkDay,
COALESCE(cte.[Next Day], s.WorkDay) AS [Adjusted Date Excluding holidays and weekends]
FROM
@Schedule s
LEFT JOIN AggregateCTE cte ON s.[WorkDay] = cte.[Weekends & Holidays]
如果您只想查看已调整的日期,则使用INNER JOIN AggregateCTE
代替LEFT JOIN AggregateCTE
。如果可能的话,我还建议按开始日期和结束日期范围过滤WITH RecursiveCTE
cte。
答案 1 :(得分:2)
<强> SQL Fiddle Demo 强>
SELECT MIN(allDays.dte)
FROM (
SELECT '2015-01-01' + INTERVAL ones.a + 10*tens.a + 100*hundred.a DAY dte
FROM
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) ones,
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) tens,
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) hundred
WHERE '2015-01-01' + INTERVAL ones.a + 10*tens.a + 100*hundred.a DAY < '2016-01-01'
) allDays
LEFT JOIN holidays H
ON allDays.dte = H.holydate
WHERE
H.holydate IS NULL
AND allDays.dte >= '2015-12-12' -- HERE go your Source DATE
<强>输出强>
| MIN(allDays.dte) |
|------------------|
| 2015-12-14 | --Because 12 and 13 are holidays
<强> EXPLAIN 强>
首先,您需要为allDays创建一个列表。在这里,我生成一个子查询来列出2015
的所有日期,您需要适应大范围。
SELECT '2015-01-01' + INTERVAL ones.a + 10*tens.a + 100*hundred.a DAY dte
FROM
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) ones,
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) tens,
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 ) hundred
WHERE '2015-01-01' + INTERVAL ones.a + 10*tens.a + 100*hundred.a DAY < '2016-01-01'
然后执行left join
以查看DATE是否为假日
LEFT JOIN holidays H
ON allDays.dte = H.holydate
最后选择不假期的较小日期
WHERE H.holydate IS NULL -- NULL mean doesnt have a match in the holiday table
AND allDays.dte >= '2015-12-12' -- HERE go your Source DATE
答案 2 :(得分:2)
我建议创建一个函数,根据包含周末和假日的表递归验证下一个工作日。这种方法的优点是,无论何时需要,它都是可重用的功能。
此功能接收日期和时间。 (根据您问题中的代码)如果时间是在下午5点之后,则添加一天。之后,继续检查日期是否在周末或节假日之前,直到找到下一个工作日:
CREATE FUNCTION dbo.adjustedDate(@dateReceived DATETIME, @timeReceived TIME)
RETURNS DATETIME
AS
BEGIN
DECLARE @adjustedDate DATETIME = @dateReceived
-- Verify time to add 1 day to @adjustedDate
IF @timeReceived IS NOT NULL
IF @timeReceived > CONVERT(TIME, '5:00:00 PM')
SET @adjustedDate = DATEADD(DAY, 1, @adjustedDate)
-- Continue adding 1 day to @adjustedDate recursively until find one date that is not a weekend or holiday
IF EXISTS(SELECT [Weekends & Holidays]
FROM dbo.WeekendsHoliday
WHERE [Weekends & Holidays] = @adjustedDate)
SET @adjustedDate = dbo.adjustedDate(DATEADD(DAY, 1, @adjustedDate), NULL)
RETURN @adjustedDate
END
答案 3 :(得分:0)
我创建了非常简单的代码,在您的约会日期添加天数时将不包括假日和星期六星期日。首先,您必须为此创建假期表,然后您可以使用以下代码。我希望你能用我的代码得到你的结果,因为我创建了它并且它正常工作。
;WITH Numbers AS
(
SELECT 1 AS value
UNION ALL
SELECT value + 1 AS value
FROM Numbers
WHERE Numbers.value <= 99
)
SELECT FinalTable.FromDate,FinalTable.AddedDays,FinalTable.AdjustedDate
FROM (
SELECT Final.*,ROW_Number() OVER (ORDER BY (SELECT NULL)) AS AddedDays
FROM (
SELECT tbl.FromDate,CASE WHEN DATENAME(dw,tbl.AdjustedDate) = 'Saturday' THEN 0
WHEN DATENAME(dw,tbl.AdjustedDate) = 'Sunday' THEN 0
WHEN tbl.AdjustedDate in (SELECT Holiday_Date FROM Holiday) THEN 0
ELSE 1 END AS LogicNumber ,tbl.days, tbl.AdjustedDate
FROM (
SELECT @FromDate AS FromDate, DATEADD(DAY,num,@FromDate) AS AdjustedDate, num AS days
FROM (
SELECT ROW_Number() OVER (ORDER BY (SELECT NULL)) AS num FROM Numbers
) t
WHERE num <= 100
) tbl
)Final
WHERE LogicNumber = 1
)FinalTable
WHERE AddedDays = @days
让我们说@FromDate =&#39; 2017-12-30&#39; 2018年1月1日是假期表中的假日,我们必须增加10天,即@days = 10
输出
FromDate | AddedDays | AdjustedDate
2017-12-30 | 10 | 2018-01-15