2010-07-20 15 views
5

Ho una tabella con data e ora, e voglio dividere questo tavolo in intervalli di un'ora, iniziando ora e andando indietro di un paio d'ore. Non riesco a ottenere i risultati che mi servono con la funzione T-SQL DATEDIFF, poiché conta il numero di volte in cui la lancetta dei minuti passa 12 tra le due date: voglio il numero di volte in cui la lancetta dei minuti passa dove è ora tra il timestamp e ora.DateDiff T-SQL - partizione di "ore complete fa", piuttosto che "minuti in minuti 00 da"

C'è un modo semplice per farlo in T-SQL?

Aggiornamento: In risposta ai commenti, ecco alcuni dati di esempio, la query Attualmente sto usando ed i risultati che sto ottenendo, così come i risultati che voglio.

dati del campione:

TimeStamp 
********* 
2010-07-20 11:00:00.000 
2010-07-20 10:44:00.000 
2010-07-20 10:14:00.000 
2010-07-20 11:00:00.000 
2010-07-20 11:40:00.000 
2010-07-20 10:16:00.000 
2010-07-20 13:00:00.000 
2010-07-20 12:58:00.000 

interrogazione attuale:

SELECT TimeStamp, DATEDIFF(HOUR, TimeStamp, CURRENT_TIMESTAMP) AS Diff FROM ... 

Risultati:

 TimeStamp     Diff 
    *********     **** 
    2010-07-20 11:00:00.000  2 
    2010-07-20 10:44:00.000  3 
    2010-07-20 10:14:00.000  3 
    2010-07-20 11:00:00.000  2 
    2010-07-20 11:40:00.000  2 
    2010-07-20 10:16:00.000  3 
    2010-07-20 13:00:00.000  0 
    2010-07-20 12:58:00.000  1

Cosa avrei preferito:

 -- The time is now, for the sake of the example, 13:40 

    TimeStamp     Diff 
    *********     **** 
    2010-07-20 11:00:00.000  3 -- +1 
    2010-07-20 10:44:00.000  3 
    2010-07-20 10:14:00.000  4 -- +1 
    2010-07-20 11:00:00.000  3 -- +1 
    2010-07-20 11:40:00.000  2 or 3 -- edge case, I don't really care which 
    2010-07-20 10:16:00.000  4 -- +1 
    2010-07-20 13:00:00.000  1 -- +1 
    2010-07-20 12:58:00.000  1

Ho contrassegnato i risultati modificati con +1. Inoltre, non mi importa se questo è 0-indicizzato o 1-indicizzato, ma in fondo, se è ora 13:40 Voglio che i periodi di tempo che ottengono lo stesso valore di essere

 12:40-13:40 1 (or 0) 
    11:40-12:40 2 (or 1) 
    10:40-11:40 3 (or 2) 
    09:40-10:40 4 (or 3)
+0

si può spiegare che con i dati di input e output previsto con il domanda, hai scritto? – shahkalpesh

+0

DATEDIFF in pochi minuti quindi divisione intera per 60? –

risposta

7

può non basta usare DATEDIFF(minute,.. e poi dividere il risultato per 60 e prendere il valore intero. per esempio.

SELECT DATEDIFF(minute, '2010-07-20 06:00', GETDATE())/60 

Credo che questo sarà implicitamente lanciato come un int come datediff restituisce un int, dà ore intere senza arrotondamenti.

Per usare la query esatto dal tuo post aggiornamento:

SELECT TimeStamp, (DATEDIFF(minute, TimeStamp, CURRENT_TIMESTAMP) /60) AS Diff FROM ... 
+0

Questo non sarà ancora preciso. Hai appena cambiato l'errore da 59 minuti a 59 secondi ... – ErikE

+0

@Emtucifor: Un errore di 59 secondi è ancora molto meglio - lo userò per decidere se un utente debba ricevere una notifica o meno, e dovrebbero arrivare al massimo una all'ora. Un errore di 59 minuti in quel caso è catastrofico - un errore di 59 secondi è piuttosto buono. E posso persino ottenere che l'errore sia ancora più piccolo (<1 secondo) facendo la stessa cosa con i secondi di Ben con i minuti. –

+0

Ok, nessun problema allora. Mi piace anche la mia versione delle date di sottrazione, perché è ancora più semplice ed è esatta quanto consente il tipo di dati. :) – ErikE

0

È possibile raggruppare su questo:

SELECT DateDiff(Hour, 0, GetDate() - TimeStamp) 

Se si vuole conoscere il tempo questo rappresenta, calc indietro:

DateAdd(Hour, -DateDiff(Hour, 0, GetDate() - TimeStamp), GetDate()) 

Se non ti piacciono le date di sottrazione, allora può ancora essere fatto ma diventa un po 'più difficile. Invece di sparare al buio, ho elaborato una query per dimostrare che è corretto.

SELECT 
    TimeStamp, 
    Now = GetDate(), 
    HourDiff = DateDiff(Hour, 0, GetDate() - TimeStamp), 
    HourCalc = DateAdd(Hour, -DateDiff(Hour, 0, GetDate() - TimeStamp), GetDate()), 
    HourDiff2 = DateDiff(Hour, DateAdd(Millisecond, AdjustMs, TimeStamp), DateAdd(Millisecond, AdjustMs, GetDate())), 
    HourCalc2 = DateAdd(Hour, -DateDiff(Hour, DateAdd(Millisecond, AdjustMs, TimeStamp), DateAdd(Millisecond, AdjustMs, GetDate())), GetDate()) 
FROM 
    (
     SELECT DateAdd(Second, -3559, GetDate()) 
     UNION ALL SELECT DateAdd(Second, -3600, GetDate()) 
     UNION ALL SELECT DateAdd(Second, -3601, GetDate()) 
    ) x (TimeStamp) 
    CROSS JOIN (
     SELECT 3599997 - DateDiff(Millisecond, 0, DateAdd(Hour, -DateDiff(Hour, 0, GetDate()), GetDate())) 
    ) D (AdjustMs) 

Purtroppo, ho avuto di sfruttare la mia conoscenza della risoluzione del tipo di dati datetime (1/300 ° di secondo), quindi 3.600.000-3 = 3599997. Se la regolazione millisecondo è stato calcolato sulla base della TimeStamp invece di GetDate () quindi non sarebbe necessario, ma sarebbe molto più complicato dal momento che la grande espressione all'interno della tabella derivata D dovrebbe essere utilizzata due volte nella query principale, sostituendo AdjustMs.

I calcoli sono più complicati di quanto potrebbe sembrare necessario perché non è possibile calcolare semplicemente la differenza di millisecondi tra le date casuali o si verificherà un errore di overflow. Se conosci gli intervalli di date possibili, potresti essere in grado di farla franca eseguendo calcoli diretti al millisecondo utilizzando una data di ancoraggio diversa da '19000101 00: 00: 00.000' (lo 0 nelle espressioni sopra).

A pensarci bene, si ottiene solo 24+ giorni di millisecondi in un lungo firmato:

SELECT DateAdd(Millisecond, 2147483647, 0) = '1900-01-25 20:31:23.647' 
+0

Sembra una lunga strada per evitare di sottrarre le date, ma dal tuo post lo prendo potrebbero esserci buone ragioni per non volerlo fare. Perché non dovrei voler sottrarre le date? –

+0

Bene, in questo caso non è un requisito con ** datetime **, ma in SQL Server 2008 non è possibile aggiungere o sottrarre valori del tipo di dati ** date **. Anche se farlo con ** datetime ** funziona per ora, potrebbe non durare per sempre. C# .Net proibisce anche questo (puoi solo aggiungere e sottrarre i tempi a partire da date o altri tempi), quindi dovremmo tutti pensare a dei modi per evitarlo se continueremo a stare al passo con queste cose a lungo termine. Qualche giorno di tempo di sottrazione potrebbe essere deprecato e quindi rimosso come caratteristica! – ErikE

0

userei

FLOOR(24 * CAST(CURRENT_TIMESTAMP-[TimeStamp] as float)) 

Test Case

DECLARE @GetDate datetime 
set @GetDate = '2010-07-20 13:40:00.000'; 

WITH TestData As 
(
select CAST('2010-07-20 11:00:00.000' AS DATETIME) AS [TimeStamp] UNION ALL 
select '2010-07-20 10:44:00.000' UNION ALL  
select '2010-07-20 10:14:00.000' UNION ALL 
select '2010-07-20 11:00:00.000' UNION ALL 
select '2010-07-20 11:40:00.000' UNION ALL 
select '2010-07-20 10:16:00.000' UNION ALL 
select '2010-07-20 13:00:00.000' UNION ALL 
select '2010-07-20 12:58:00.000' 
) 

SELECT [TimeStamp], FLOOR(24 * CAST(@GetDate-[TimeStamp] as float)) AS Diff 
FROM TestData 

Risultati

(Si avrebbe bisogno di aggiungere 1 per ottenere i risultati esatti in cui hai postato, ma lei dice che non si è preoccupato di 0 o 1 indicizzato)

TimeStamp    Diff 
----------------------- ---------------------- 
2010-07-20 11:00:00.000 2 
2010-07-20 10:44:00.000 2 
2010-07-20 10:14:00.000 3 
2010-07-20 11:00:00.000 2 
2010-07-20 11:40:00.000 2 
2010-07-20 10:16:00.000 3 
2010-07-20 13:00:00.000 0 
2010-07-20 12:58:00.000 0 
+0

Perché il '24 *'? Cosa mi dà 'CAST (@ GetDate- [TimeStamp] AS FLOAT)? –

+0

@Tomas. 'CAST (@ GetDate- [TimeStamp] AS FLOAT)' è il numero di giorni di differenza. per esempio. 1,75 sarebbe 1 giorno e 18 ore di differenza. Quindi moltiplicando per 24 si ottiene il numero di ore di differenza. Usando 'Piano' quindi raggruppa tutto in un'ora insieme. –

+0

Martin, nella mia esperienza la conversione in float non è affidabile per datetime. L'ho studiato attentamente nel passato. Datediff (Hour, 0, Current_TimeStamp - TimeStamp) fa lo stesso trucco. – ErikE

Problemi correlati