sql >> Base de Datos >  >> RDS >> Sqlserver

T-SQL obtiene el número de días hábiles entre 2 fechas

Por favor, por favor, utilice una tabla de calendario. SQL Server no sabe nada sobre feriados nacionales, eventos de la empresa, desastres naturales, etc. Una tabla de calendario es bastante fácil de crear, ocupa muy poco espacio y estará en la memoria si se hace suficiente referencia a ella.

Aquí hay un ejemplo que crea una tabla de calendario con 30 años de fechas (2000 -> 2029) pero requiere solo 200 KB en el disco (136 KB si usa compresión de página). Casi se garantiza que sea menor que la concesión de memoria requerida para procesar algún CTE u otro conjunto en tiempo de ejecución.

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.

Ahora la consulta que está buscando es bastante simple de escribir:

SELECT COUNT(*) FROM dbo.Calendar
  WHERE dt >= '20130110'
    AND dt <  '20130115'
    AND IsWorkDay = 1;

Más información sobre tablas de calendario:

http://web.archive.org/web/20070611150639/http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-calendar-table.html

Más información sobre conjuntos generadores sin bucles:

http://www.sqlperformance.com/tag/date-ranges

También tenga cuidado con pequeñas cosas como confiar en la salida en inglés de DATENAME . He visto fallas en varias aplicaciones porque algunos usuarios tenían una configuración de idioma diferente, y si confía en WEEKDAY asegúrese de configurar su DATEFIRST configurando apropiadamente...