14 votes

SQL Server 2008 Générer une série de dates-horaires

J'essaie de générer un tableau contenant une série de dates et d'heures.

J'ai la date de début et la date de fin spécifiées (la date de fin correspond à la fin de la séquence), j'ajoute un intervalle de temps ~ (qui peut varier) à la date de début en secondes et cela me donne la date de fin.

La séquence suivante utilise la date et l'heure de fin comme valeur de départ et y ajoute l'intervalle de temps en secondes. Pour démontrer la sortie dont j'ai besoin. Existe-t-il un moyen rapide de créer ce type de tableau, à part l'utilisation de nombreuses commandes d'insertion dans le tableau ?

StartTime               Endtime                 Duration
2011-07-20 11:00:33     2011-07-20 11:09:47     554
2011-07-20 11:09:47     2011-07-20 11:19:01     554

    declare @StartTime datetime = '2011-07-20 11:00:33',
    @EndTime datetime = '2011-07-20 15:37:34'
    @Interval int = 554 -- this can be changed.

    insert into tmp_IRange
    values('2011-07-20 11:00:33', DATEADD(SECONDS, @Duration, 2011-07-20 11:00:33))

cela devient très fastidieux surtout lorsque l'heure de la date de fin est 2011-07-20 15:37:34 il y a beaucoup de déclarations d'insertion à faire :(

19voto

gbn Points 197263

Utiliser un CTE récursif

declare @StartTime datetime = '2011-07-20 11:00:33',
    @EndTime datetime = '2011-07-20 15:37:34',
    @Interval int = 554 -- this can be changed.

;WITH cSequence AS
(
    SELECT
       @StartTime AS StartRange, 
       DATEADD(SECOND, @Interval, @StartTime) AS EndRange
    UNION ALL
    SELECT
      EndRange, 
      DATEADD(SECOND, @Interval, EndRange)
    FROM cSequence 
    WHERE DATEADD(SECOND, @Interval, EndRange) < @EndTime
)
 /* insert into tmp_IRange */
SELECT * FROM cSequence OPTION (MAXRECURSION 0);

5voto

Aaron Bertrand Points 116343

Celui-ci donnera les plages individuelles mais ignorera votre heure de fin réelle (puisqu'elle est < @intervalle après la dernière plage valide) :

;WITH x AS 
(
    SELECT TOP (DATEDIFF(SECOND, @StartTime, @EndTime)/@Interval) 
        rn = ROW_NUMBER() OVER (ORDER BY [object_id])
    FROM sys.objects
)
-- INSERT INTO dbo.tmp_IRange
SELECT DATEADD(SECOND, @Interval * (rn-1), @StartTime),
    DATEADD(SECOND, @Interval * rn, @StartTime)
FROM x;

4voto

Yuck Points 23174

Cela devrait vous permettre de commencer. Vous pouvez l'adapter à vos besoins spécifiques. Tel qu'il est écrit, il générera une ligne pour chaque incrément de minute en commençant par la date et l'heure actuelles.

DECLARE @BaseDate DateTime = GETDATE();

WITH DateTable (DateValue) AS (
    SELECT @BaseDate DateValue
    UNION ALL
    SELECT DATEADD(Minute, 1, DateValue) DateValue
    FROM DateTable
)
SELECT *
FROM DateTable
WHERE DateValue < DATEADD(Day, 1, GETDATE())
OPTION (MAXRECURSION 0);

4voto

Andriy M Points 40395

Voici une autre solution non récursive basée sur les ensembles, qui utilise une table système appelée master..spt_values :

DECLARE
  @StartTime datetime = '2011-07-20 11:00:33',
  @EndTime datetime = '2011-07-20 15:37:34',
  @Interval int = 554;
SELECT
  StartTime = DATEADD(SECOND, (number - 1) * @Interval, @StartTime),
  EndTime   = DATEADD(SECOND, (number - 0) * @Interval, @StartTime),
  Duration  = @Interval
FROM master..spt_values
WHERE type = 'P'
  AND number BETWEEN 1 AND DATEDIFF(SECOND, @StartTime, @Endtime) / @Interval

UNION ALL

SELECT
  DATEADD(SECOND, -Duration, EndTime),
  EndTime,
  Duration
FROM (
  SELECT
    EndTime = @EndTime,
    Duration = DATEDIFF(SECOND, @StartTime, @Endtime) % @Interval
) s
WHERE Duration > 0

Le premier SELECT génère un ensemble de lignes constitué de courts intervalles d'une longueur donnée qui se situent dans la plage spécifiée. Si nécessaire, le second SELECT ajoute un intervalle entre l'heure de fin du dernier intervalle du premier SELECT et l'heure de fin spécifiée.

Le sous-ensemble de master..spt_values qui est particulièrement utilisé ici (et peut être utilisé dans de nombreux cas similaires) fournit une liste de nombres de 0 à 2047. Cela signifie pour vous que vous ne pourrez pas utiliser cette solution avec cette table si l'intervalle initial doit être divisé en plus de 2047 intervalles courts. Vous devez alors penser à quelque chose comme votre propre [table des nombres](http://www.sqlservercentral.com/articles/T-SQL/62867/ "The "Numbers" or "Tally" Table: What it is and how it replaces a loop.") .

0voto

teenboy Points 298

J'espère que cela vous aidera...

declare @StartTime datetime = '2011-07-20 11:00:33',
@EndTime datetime = '2011-07-20 11:00:33',
@Interval int = 554,

@LimitTime datetime = '2011-07-20 15:37:34'

WHILE @EndTime < @LimitTime
BEGIN
SELECT @EndTime = DATEADD(S, @Interval, @StartTime)

SELECT @StartTime, @EndTime
--INSERT INTO tmp_IRange VALUES(@StartTime, @EndTime)

SELECT @StartTime = @EndTime

END

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