Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

T-SQL obtém número de dias úteis entre 2 datas


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...