Моля, моля, използвайте календарна таблица. SQL Server не знае нищо за национални празници, фирмени събития, природни бедствия и т.н. Календарната таблица е сравнително лесна за изграждане, заема изключително малко пространство и ще бъде в паметта, ако е достатъчно реферирана.
Ето пример, който създава календарна таблица с 30 години дати (2000 -> 2029), но изисква само 200 KB на диск (136 KB, ако използвате компресиране на страници). Това е почти гарантирано по-малко от предоставената памет, необходима за обработка на някакъв CTE или друг набор по време на изпълнение.
CREATE TABLE dbo.Calendar
(
dt DATE PRIMARY KEY, -- use SMALLDATETIME if < SQL Server 2008
IsWorkDay BIT
);
DECLARE @s DATE, @e DATE;
SELECT @s = '2000-01-01' , @e = '2029-12-31';
INSERT dbo.Calendar(dt, IsWorkDay)
SELECT DATEADD(DAY, n-1, '2000-01-01'), 1
FROM
(
SELECT TOP (DATEDIFF(DAY, @s, @e)+1) ROW_NUMBER()
OVER (ORDER BY s1.[object_id])
FROM sys.all_objects AS s1
CROSS JOIN sys.all_objects AS s2
) AS x(n);
SET DATEFIRST 1;
-- weekends
UPDATE dbo.Calendar SET IsWorkDay = 0
WHERE DATEPART(WEEKDAY, dt) IN (6,7);
-- Christmas
UPDATE dbo.Calendar SET IsWorkDay = 0
WHERE MONTH(dt) = 12
AND DAY(dt) = 25
AND IsWorkDay = 1;
-- continue with other holidays, known company events, etc.
Сега заявката, която търсите, е доста лесна за писане:
SELECT COUNT(*) FROM dbo.Calendar
WHERE dt >= '20130110'
AND dt < '20130115'
AND IsWorkDay = 1;
Повече информация за календарните таблици:
http://web.archive.org/web/20070611150639/http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-calendar-table.html
Повече информация за генериране на набори без цикли:
http://www.sqlperformance.com/tag/date-ranges
Също така се пазете от малки неща като разчитане на изхода на английски език на DATENAME
. Виждал съм няколко приложения да се повредят, защото някои потребители са имали различна езикова настройка и ако разчитате на WEEKDAY
уверете се, че сте задали своя DATEFIRST
подходяща настройка...