63 votes

Générer des dates entre des plages de dates

J'ai besoin de remplir une table qui stockera les plages de dates entre 2 dates données : 01/09/11 - 10/10/11

Donc, dans ce cas, la table commencerait à partir du 01/09/11 et serait stockée chaque jour jusqu'au 10/10/11 Je me demandais s'il existait un moyen astucieux de le faire dans SQL Server - j'utilise actuellement SQL Server 2008. Merci

84voto

Stuart Ainsworth Points 7529

Facile sur SQL 2005+ ; plus facile si vous avez un nombre ou une table de pointage. Je l'ai truqué ci-dessous :

 DECLARE @StartDate DATE = '20110901'
  , @EndDate DATE = '20111001'

SELECT  DATEADD(DAY, nbr - 1, @StartDate)
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY c.object_id ) AS Nbr
          FROM      sys.columns c
        ) nbrs
WHERE   nbr - 1 <= DATEDIFF(DAY, @StartDate, @EndDate)

Si vous avez une table de pointage, remplacez la sous-requête par la table. Pas de récursivité.

57voto

Abe Miessler Points 34869

Essayez ceci si vous utilisez SQL Server 2005 ou une version plus récente :

 WITH Dates AS (
        SELECT
         [Date] = CONVERT(DATETIME,'09/01/2011')
        UNION ALL SELECT
         [Date] = DATEADD(DAY, 1, [Date])
        FROM
         Dates
        WHERE
         Date < '10/10/2011'
) SELECT
 [Date]
FROM
 Dates
 OPTION (MAXRECURSION 45)

Un bon exemple de trucs sympas que vous pouvez faire avec un CTE.

19voto

sll Points 30638

-- Déclarations

 DECLARE @dates TABLE(dt datetime)    
DECLARE @dateFrom datetime
DECLARE @dateTo datetime

SET @dateFrom = '2001/01/01'
SET @dateTo = '2001/01/12'

-- Requête :

 WHILE(@dateFrom < @dateTo)
BEGIN
   SELECT @dateFrom = DATEADD(day, 1,@dateFrom)
   INSERT INTO @dates 
   SELECT @dateFrom
END

-- Sortie

 SELECT * FROM @dates

14voto

sken130 Points 21

Voici une solution qui ne nécessite pas de récursivité, et en même temps, cette fonction table est réutilisable dans de nombreuses requêtes sans qu'il soit nécessaire de répéter à nouveau la déclaration des variables passe-partout. C'est la seule alternative, pour ceux qui ne veulent pas de récursivité.

Créez cette fonction simple :

 CREATE FUNCTION [dbo].[GenerateDateRange]
(@StartDate AS DATE,
 @EndDate AS   DATE,
 @Interval AS  INT
)
RETURNS @Dates TABLE(DateValue DATE)
AS
BEGIN
    DECLARE @CUR_DATE DATE
    SET @CUR_DATE = @StartDate
    WHILE @CUR_DATE <= @EndDate BEGIN
        INSERT INTO @Dates VALUES(@CUR_DATE)
        SET @CUR_DATE = DATEADD(DAY, @Interval, @CUR_DATE)
    END
    RETURN;
END;

Et puis sélectionnez par :

 select *
from dbo.GenerateDateRange('2017-01-03', '2017-12-01', 1)

9voto

SQL RV Points 51

Je me rends compte que c'est un vieux fil, mais je dois admettre ma consternation devant la surabondance de solutions récursives et en boucle données ici. Je me demande combien de personnes réalisent que la récursivité n'est rien de plus qu'une boucle très coûteuse ? Je comprends le désir de créer une fonction table, mais je suggère que ce qui suit est beaucoup plus efficace car il est basé sur des ensembles, sans boucle, récursivité ou instructions d'insertion simples répétées :

 CREATE FUNCTION dbo.GenerateDateRange(@StartDate AS DATE, @EndDate AS DATE)
RETURNS TABLE WITH SCHEMABINDING AS
    WITH e1(n) AS (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS x(n)) -- 16 records
        ,e2(n) AS (SELECT 1 FROM e1 a CROSS JOIN e1 b) -- 16^2 or 256 records (16*16)
        ,cteTally(n) AS (SELECT ROW_NUMBER() over (ORDER BY 1) AS n FROM e2 a CROSS JOIN e2 b) -- 16^4 or 65,536 records (256*256)
    SELECT DATEADD(DAY, n-1, @StartDate)
    FROM cteTally
    WHERE n <= DATEDIFF(DAY, @StartDate, @EndDate) + 1;
GO

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X