2011-08-22 25 views
13

Estoy tratando de generar una tabla con una serie de fechas.SQL Server 2008 Generar una serie de fechas

Tengo la fecha de inicio y la fecha de finalización especificadas (la fecha de finalización es el final de la secuencia), agrego un intervalo de tiempo ~ (esto puede variar) a la fecha de inicio en segundos y esto me da la fecha final hora.

La secuencia siguiente usa el tiempo de fecha de finalización como su valor de inicio y agrega el intervalo de tiempo en segundos. Para demostrar el resultado que necesito. ¿Hay una forma rápida de crear una tabla de este tipo, con excepción de usar una gran cantidad de inserción en comandos ?, estoy realmente confundido

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

esto se vuelve muy tedioso .. sobre todo cuando el tiempo de la fecha final es 2011-07-20 15:37:34 existen una gran cantidad de instrucciones de inserción para hacer :(

+2

Realmente no demostró su salida. ¿Puedes mostrar las tres primeras y las últimas tres filas que realmente quieres? –

+1

Tenga en cuenta que las respuestas basadas en CTE recursivas tienen un límite de 32767 niveles de recursión. (Consulte la documentación de MAXRECURSION.) – HABO

+2

@ user92546 - Ese no es el caso. 'MAXRECURSION 0' es ilimitado. –

Respuesta

4

Esto debería empezar. se puede adaptar a sus necesidades específicas. Como se ha dicho que va a generar una fila para cada incremento minutos a partir de la fecha actual & tiempo.

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); 
+0

Hace incrementos de 1 segundo, ¿verdad? – JNK

+0

@JNK: Sí, editó la descripción y los incrementos. ¡Tal como estaba, la consulta se ejecutaría durante bastante tiempo! – Yuck

+0

Bueno, solo tiene una única variable de fecha y hora, mientras que el OP tiene dos variables de fecha y hora y un intervalo.¿Por qué no hay nada en su solución sobre el intervalo (554 segundos) y la fecha de finalización (suponiendo que es un intervalo de 1 minuto en un solo día)? –

16

Usar un CTE recursiva

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); 
+0

Se utiliza Intervalo en esta consulta, parece que la duración de la variable no declarada en esta consulta. – jrara

+0

@jrara: gracias, fijo – gbn

+0

Funciona bien, gracias – mouse

5

Ésta dará los rangos individuales, pero ignorará su tiempo final real (ya que es < @interval después del último intervalo válido):

;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; 
+0

* 'La siguiente secuencia usa el tiempo de fecha de finalización como su valor de inicio' *, lo que significa que la hora de inicio no es un valor fijo. –

+0

Gracias @Andriy, lo perdí; eliminó la primera respuesta. –

0

Esperanza esta ayuda ...

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 
0

favor intente este código:

create table #T (date_begin datetime, date_end datetime)  

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

while DATEADD(ss,@Interval,@StartTime)<[email protected] 
begin 
    insert #T 
    select @StartTime, DATEADD(ss,@Interval,@StartTime) 

    set @StartTime = DATEADD(ss,@Interval,@StartTime) 
end 


select * from #T 
3

Aquí es otra solución basada en conjunto no recursiva, que utiliza una tabla de sistema llamado 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 

La primera SELECT genera un conjunto de filas consiste en cortos intervalos de longitud especificada que se encuentran dentro del rango especificado. Si es necesario, el segundo SELECT agrega un intervalo entre el tiempo de finalización del último intervalo del primer SELECT y el tiempo de finalización especificado.

El subconjunto de master..spt_values que se utiliza especialmente aquí (y se puede usar en muchos casos similares) proporciona una lista de números del 0 al 2047. Esto significa para usted que no podrá usar esta solución con esa tabla si el intervalo inicial se dividirá en más de 2047 intervalos cortos (er). Entonces debería pensar en algo como su propio number table.

+0

+1, pero llámelo número o tabla de números, no una tabla de conteo. Es una tabla de números, no una tabla de sumas. :-) –

+0

¡No hay problema! Pensé que los dos términos eran completamente intercambiables. Aunque admito, no puedo entender completamente todas las sutilezas del significado de la palabra * tally * (y se deduce que debería haber sido más cauteloso en mis usos anteriores del término * tabla de recuento *). ¡Muchas gracias por el aviso! –

+1

Jeff Moden está tratando de "reinventar" la idea de la tabla de números (que no se originó de él) al renombrarla. De modo que las discusiones evolucionan donde dos personas usan términos diferentes, y puede ser confuso. La tabla de números * puede * usarse para el recuento, pero ese es solo un caso de uso muy específico, incluso si es uno de los más comunes. De todos modos, esta es solo mi opinión, totalmente subjetiva, pero trato de derribar la proliferación del término "tabla de recuento" cuando creo que la gente podría escuchar. :-) –

Cuestiones relacionadas