2012-06-25 13 views
6

Ho una colonna datetime con intervallo di valori Datetime. Voglio creare un'altra colonna con tutti questi valori datetime ma arrotondare per difetto a dieci minuti.Ottenere gli intervalli di dieci minuti da un intervallo di datatempo

Quindi, qualcosa di simile:

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

il più lontano che ho ottenuto è giocare in giro con sta ricevendo negli slot secchio minuto. ho ottenuto questo facendo:

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

Ma ho bisogno di dieci slot minuto secchio.

+0

Prova: http://stackoverflow.com/questions/249794/how-to-round-a-tempo-in-T-SQL. Questo post ha anche molti esempi: http://stackoverflow.com/questions/830792/t-sql-round-to-nearest-15-minute-interval –

risposta

8

Prova questo:

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 intelligente e ordinato –

0

Supponendo che non ci sono mai millisecondi, si può spogliare minuti e secondi in questo modo, e di gruppo sul risultato:

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

Ecco una query che ottiene il giusto numero di slot di tempo in base al min e max date dalla tabella (o un sottoinsieme della tabella):

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 ...; 

risultati:

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

È possibile farlo usando un sacco di funzioni:

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 

L'essenza di questo è Escludendo il numero di minuti dopo un intervallo di 10 minuti e deducendo questo dal numero effettivo di minuti (con i secondi rimosso).

Questo può essere riordinato un po 'spostando alcune delle funzioni in un join. Tuttavia, non credo che questo offre alcun guadagno di prestazioni (non fatto alcun test a tutti)

;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

Non sembra pulito come la risposta accettata, ma questo è SICURAMENTE la risposta corretta a questa domanda! – 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 
Problemi correlati