2012-06-25 16 views
6

Tengo una columna de fecha y hora con un rango de valores de fecha y hora. Quiero crear otra columna con todos estos valores de fecha y hora, pero para redondear a un período de diez minutos.Obtenga los intervalos de diez minutos de un intervalo de fechas

Por lo tanto, algo como esto:

datetimesent    |  ten_minute_column 

2012-06-11 18:27:58.000 |  2012-06-11 18:20:00.000 
2012-06-15 15:19:08.000 |  2012-06-15 15:10:00.000 
...      | 

Lo más lejos que he llegado es a jugar con es conseguir que en las ranuras de cubo minuto. Tengo esta haciendo:

SELECT DatetimeSent, 
    DATEADD(Minute, DATEDIFF(Minute, 0, DatetimeSent), 0) AS Minute_bucket 
FROM allrequests 

Pero necesito diez minutos ranuras de cubo.

+0

Probar: http://stackoverflow.com/questions/249794/how-to-round-a-time-in-t-sql. Esta publicación también tiene muchos ejemplos: http://stackoverflow.com/questions/830792/t-sql-round-to-nearest-15-minute-interval –

Respuesta

8

Prueba esto:

select dateadd(minute, datepart(minute, datetimesent)/10 * 10, 
dateadd(hour, datediff(hour, 0,datetimesent), 0)) ten_minute_column 
from 
(select cast('2012-06-11 18:27:58.000' as datetime) datetimesent 
union all 
select cast('2012-06-15 15:19:08.000' as datetime)) a 
+0

+1 inteligente y ordenado –

0

Suponiendo que nunca hay milisegundos, se puede despojar minutos y segundos de esta manera, y el grupo en el resultado:

SELECT DATEADD(SECOND, -(CONVERT(INT, RIGHT(CONVERT(CHAR(2), 
    DATEPART(MINUTE, GETDATE())),1))*60)-(DATEPART(SECOND,GETDATE())), GETDATE()); 

Aquí es una consulta que obtiene el número correcto de intervalos de tiempo sobre la base de los valores mínimo y máximo fechas de la tabla (o un subconjunto de la tabla):

DECLARE @x TABLE(datetimesent DATETIME); 
INSERT @x SELECT '2012-06-11 18:27:58.000' 
UNION ALL SELECT '2012-06-15 15:19:08.000'; 

DECLARE @start SMALLDATETIME, @end SMALLDATETIME, @i INT; 

SELECT @start = CONVERT(DATE, MIN(datetimesent)), @end = CONVERT(DATE, 
MAX(datetimesent)) 
FROM @x 
-- WHERE ...; 

SELECT @i = DATEDIFF(DAY, @start, @end) * 144; 

;WITH slots(ten_minute_column) AS 
(
    SELECT TOP (@i * 144) DATEADD(MINUTE, 10 * (ROW_NUMBER() OVER 
    (ORDER BY s1.[object_id])-1), @start) 
    FROM sys.all_columns AS s1 
    -- you may need to cross join to another table if this doesn't 
    -- provide enough rows. Depends on overall datediff... 
) 
SELECT x.datetimesent, slots.ten_minute_column 
FROM @x AS x 
INNER JOIN slots 
ON x.datetimesent >= slots.ten_minute_column 
AND x.datetimesent < DATEADD(MINUTE, 10, slots.ten_minute_column) 
-- WHERE ...; 

Resultados:

datetimesent    ten_minute_column 
----------------------- ------------------- 
2012-06-11 18:27:58.000 2012-06-11 18:20:00 
2012-06-15 15:19:08.000 2012-06-15 15:10:00 
3

Usted puede hacer esto utilizando una gran cantidad de funciones:

WITH D AS 
( SELECT CURRENT_TIMESTAMP [DateField] 
    UNION ALL 
    SELECT DATEADD(MINUTE, 5, CURRENT_TIMESTAMP) 
) 
SELECT DATEADD(MINUTE, (10 * FLOOR(DATEPART(MINUTE, DateField)/10.0)) - DATEPART(MINUTE, DateField), DATEADD(MINUTE, DATEDIFF(MINUTE, 0, DateField), 0)) AS RoundedDate 
FROM D 

La esencia de esto se Excluyendo el número de minutos después de un intervalo de 10 minutos y deduciendo esto desde el número real de minutos (con segundos eliminado).

Esto se puede arreglar un poco moviendo algunas de las funciones a una unión. Sin embargo, no creo que esto ofrece ninguna mejora en el rendimiento (no hecho ninguna prueba en absoluto)

;WITH T AS 
( SELECT Number, 
      (10 * FLOOR(Number/10.0)) - Number [RoundedDifference] 
    FROM ( SELECT ROW_NUMBER() OVER(ORDER BY Object_ID) - 1 [Number] 
       FROM sys.All_Objects 
      ) n 
    WHERE Number < 60 
), D AS 
( SELECT CURRENT_TIMESTAMP [DateField] 
    UNION ALL 
    SELECT DATEADD(MINUTE, 5, CURRENT_TIMESTAMP) 
) 
SELECT DateField, 
     DATEADD(MINUTE, RoundedDifference, DATEADD(MINUTE, DATEDIFF(MINUTE, 0, DateField), 0)) [RoundedDate] 
FROM D 
     INNER JOIN T 
      ON DATEPART(MINUTE, DateField) = Number 
+0

No parece tan limpio como la respuesta aceptada, pero esto ¡DEFINITIVAMENTE es la respuesta correcta a esta pregunta! – NTDLS

0
SELECT DatetimeSent, 
     Dateadd(ms, -Datepart(ms, Dateadd(minute, Datediff(minute, 0, 
                Dateadd(minute, 
                -Datepart(minute, 
                datetimesent) 
                %10, 
                datetimesent)), 0 
               ) 
       ), Dateadd(minute, Datediff(minute, 0, Dateadd(minute, 
                 - 
            Datepart( 
            minute, 
                datetimesent 
            )% 
            10, 
            datetimesent 
                )), 0)) AS Minute_bucket 
FROM allrequests 
Cuestiones relacionadas