我假设您没有日历表,尽管我强烈建议您创建一个,但您仍然可以在没有日历表的情况下实现此目的:
以下将为您提供从昨天开始向后追溯的 2047 个日期的列表(使用系统表Master..spt_values
):
WITH Dates AS
( SELECT Date = DATEADD(DAY, -number, CAST(GETDATE() AS DATE))
FROM Master..spt_values
WHERE type = 'P'
AND number > 0
)
SELECT Dates.Date
FROM Dates
ORDER BY Dates.Date DESC;
然后,您需要使用以下命令从表中排除周末和节假日:
SET DATEFIRST 1;
WITH Dates AS
( SELECT Date = DATEADD(DAY, -number, CAST(GETDATE() AS DATE))
FROM Master..spt_values
WHERE type = 'P'
AND number > 0
)
SELECT Dates.Date
FROM Dates
WHERE DATEPART(WEEKDAY, Dates.Date) <= 5
AND NOT EXISTS
( SELECT 1
FROM HolidayTable h
WHERE Dates.Date = h.HolidayDate
)
ORDER BY Dates.Date DESC;
注意您应该明确设置您的DATEFIRST
而不是依赖服务器默认值
以上为您提供了今天之前的工作日列表,然后您可以使用该ROW_NUMBER()
功能,获取列表中的第 3 次出现,给出最终查询:
WITH Dates AS
( SELECT Date = DATEADD(DAY, -number, CAST(GETDATE() AS DATE))
FROM Master..spt_values
WHERE type = 'P'
AND number > 0
), WorkingDays AS
( SELECT Dates.Date, RN = ROW_NUMBER() OVER(ORDER BY Dates.Date DESC)
FROM Dates
WHERE DATEPART(WEEKDAY, Dates.Date) <= 5
AND NOT EXISTS
( SELECT 1
FROM HolidayTable h
WHERE Dates.Date = h.HolidayDate
)
)
SELECT WorkingDays.Date
FROM WorkingDays
WHERE RN = 3;
或者,如果您愿意,可以通过一个查询来完成(与上述原理完全相同):
SELECT d.Date
FROM ( SELECT Date = DATEADD(DAY, -number, CAST(GETDATE() AS DATE)), RN = ROW_NUMBER() OVER(ORDER BY number)
FROM Master..spt_values
WHERE type = 'P'
AND number > 0
AND DATEPART(WEEKDAY, DATEADD(DAY, -number, CAST(GETDATE() AS DATE))) <= 5
AND NOT EXISTS
( SELECT 1
FROM HolidayTable h
WHERE DATEADD(DAY, -number, CAST(GETDATE() AS DATE)) = h.HolidayDate
)
) d
WHERE rn = 3;