Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

T-SQL obtient le nombre de jours ouvrables entre 2 dates

S'il vous plaît, s'il vous plaît, s'il vous plaît, utilisez un tableau de calendrier. SQL Server ne sait rien des fêtes nationales, des événements d'entreprise, des catastrophes naturelles, etc. Une table de calendrier est assez facile à construire, prend très peu d'espace et sera en mémoire si elle est suffisamment référencée.

Voici un exemple qui crée une table de calendrier avec 30 ans de dates (2000 -> 2029) mais ne nécessite que 200 Ko sur disque (136 Ko si vous utilisez la compression de page). Il est presque garanti que cela sera inférieur à l'allocation de mémoire requise pour traiter certains CTE ou autres ensembles au moment de l'exécution.

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.

Maintenant, la requête que vous recherchez est assez simple à écrire :

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

Plus d'infos sur les tableaux de calendrier :

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

Plus d'infos sur les groupes électrogènes sans boucles :

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

Méfiez-vous également des petites choses comme se fier à la sortie anglaise de DATENAME . J'ai vu plusieurs applications tomber en panne parce que certains utilisateurs avaient un paramètre de langue différent, et si vous comptez sur WEEKDAY assurez-vous de définir votre DATEFIRST réglage approprié...