Por favor, por favor, use uma tabela de calendário. O SQL Server não sabe nada sobre feriados nacionais, eventos da empresa, desastres naturais, etc. Uma tabela de calendário é bastante fácil de construir, ocupa uma quantidade extremamente pequena de espaço e estará na memória se for referenciada o suficiente.
Aqui está um exemplo que cria uma tabela de calendário com 30 anos de datas (2000 -> 2029), mas requer apenas 200 KB em disco (136 KB se você usar compactação de página). É quase garantido que isso seja menor do que a concessão de memória necessária para processar algum CTE ou outro conjunto em tempo de execução.
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.
Agora, a consulta que você procura é bastante simples de escrever:
SELECT COUNT(*) FROM dbo.Calendar
WHERE dt >= '20130110'
AND dt < '20130115'
AND IsWorkDay = 1;
Mais informações sobre tabelas de calendário:
http://web.archive.org/web/20070611150639/http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-calendar-table.html
Mais informações sobre grupos geradores sem loops:
http://www.sqlperformance.com/tag/date-ranges
Também tome cuidado com pequenas coisas como confiar na saída em inglês de
DATENAME
. Vi vários aplicativos quebrarem porque alguns usuários tinham uma configuração de idioma diferente e se você estiver confiando em WEEKDAY
certifique-se de definir seu DATEFIRST
configurando adequadamente...