2012-12-13 28 views
10

Ho una tabella SQL Server con una colonna "Ora". La tabella è una tabella di registro, contiene i messaggi di stato e i timestamp per ciascun messaggio. La tabella del registro viene inserita in un file batch. C'è una colonna ID che raggruppa le righe. Ogni volta che viene eseguito il file batch, inizializza l'ID e scrive i record. Quello che devo fare è ottenere il tempo trascorso dal primo record di un ID impostato sull'ultimo record dello stesso set di ID. Ho iniziato a giocare selezionando Max (Time) - Min (Time) da logTable dove id = ma non riuscivo a capire come formattare correttamente. Ne ho bisogno in HH: MM: SS.SQL Server: calcola il tempo trascorso tra due timbri datetime in HH: MM: formato SS

+0

Fateci sapere il tipo di dati della colonna "Ora". DateTime, DateTime2, Time, Timestamp, ecc. –

+0

@Tim ... my bad, DateTime – MikeTWebb

risposta

8

SQL Server non supporta il tipo di dati dell'intervallo standard SQL. La soluzione migliore è calcolare la differenza in secondi e utilizzare una funzione per formattare il risultato. Potrebbe sembrare che la funzione nativa CONVERT() funzioni correttamente finché l'intervallo è inferiore a 24 ore. Ma CONVERT() non è una buona soluzione per questo.

create table test (
    id integer not null, 
    ts datetime not null 
); 

insert into test values (1, '2012-01-01 08:00'); 
insert into test values (1, '2012-01-01 09:00'); 
insert into test values (1, '2012-01-01 08:30'); 
insert into test values (2, '2012-01-01 08:30'); 
insert into test values (2, '2012-01-01 10:30'); 
insert into test values (2, '2012-01-01 09:00'); 
insert into test values (3, '2012-01-01 09:00'); 
insert into test values (3, '2012-01-02 12:00'); 

valori sono stati scelti in modo tale per

  • id = 1, il tempo trascorso è di 1 ora
  • id = 2, il tempo trascorso è di 2 ore, e
  • id = 3, il tempo trascorso è di 3 ore.

Questa istruzione SELECT include una colonna che calcola i secondi e una che utilizza CONVERT() con sottrazione.

select t.id, 
     min(ts) start_time, 
     max(ts) end_time, 
     datediff(second, min(ts),max(ts)) elapsed_sec, 
     convert(varchar, max(ts) - min(ts), 108) do_not_use 
from test t 
group by t.id; 

ID START_TIME     END_TIME     ELAPSED_SEC DO_NOT_USE 
1 January, 01 2012 08:00:00 January, 01 2012 09:00:00 3600   01:00:00 
2 January, 01 2012 08:30:00 January, 01 2012 10:30:00 7200   02:00:00 
3 January, 01 2012 09:00:00 January, 02 2012 12:00:00 97200  03:00:00 

Annotare il fuorviante "03:00:00" per la differenza di 27 ore sul numero id 3.

Function to format elapsed time in SQL Server

+0

@Catcall .... domanda: la tua query ha funzionato per queste due date che sono durate più di due giorni (2012-12-13 15: 10: 12.050 e 2012-12-12 20: 16: 47.160). I tuoi risultati sono stati 68005 secondi e 18:53:24. Questo sembra giusto. Non sei sicuro del perché do_not_use 18:53:24 ci sia? – MikeTWebb

+1

CONVERT() restituisce la risposta errata per intervalli su 24 ore. La differenza tra i due timestamp è inferiore a 24 ore. La colonna "do_not_use" ha lo scopo di scoraggiare l'utente dall'utilizzare CONVERT() per formattare gli intervalli. –

+0

@Catcall ... sì, ho capito il significato della colonna "do_not_use". Ero curioso di CONVERT() .... e la tua spiegazione è perfetta. Grazie! – MikeTWebb

0

select convert(varchar, Max(Time) - Min(Time) , 108) from logTable where id=...

+0

Emetterà "03:00:00" per una differenza di 27 ore tra i due timestamp ... – XpiritO

8

aggiornamento:

calcolare correttamente un periodo in SQL Server, anche se più di 24 ore: casi

-- Setup test data 
declare @minDate datetime = '2012-12-12 20:16:47.160' 
declare @maxDate datetime = '2012-12-13 15:10:12.050' 

-- Get timespan in hh:mi:ss 
select cast(
     (cast(cast(@maxDate as float) - cast(@minDate as float) as int) * 24) /* hours over 24 */ 
     + datepart(hh, @maxDate - @minDate) /* hours */ 
     as varchar(10)) 
    + ':' + right('0' + cast(datepart(mi, @maxDate - @minDate) as varchar(2)), 2) /* minutes */ 
    + ':' + right('0' + cast(datepart(ss, @maxDate - @minDate) as varchar(2)), 2) /* seconds */ 

-- Returns 18:53:24 

bordo che mostrano inesattezza sono particolarmente benvenuti!

+0

@Tim .... questo funziona quasi. Per queste due date (2012-12-13 15: 10: 12.050 e 2012-12-12 20: 16: 47.160) la query ha restituito un risultato di 19:54:25 quando il valore effettivo è 18:53:24. Idee? – MikeTWebb

+0

@MikeTWebb si potrebbe trovare la versione corrente per funzionare bene se non si desidera utilizzare una funzione o essere limitato in quante ore possono essere rappresentati. –

1

vedere se questo aiuta. Posso impostare variabili per Giorni trascorsi, Ore, Minuti, Secondi. È possibile formattare a proprio piacimento o includere in una funzione definita dall'utente.

Nota: non utilizzare DateDiff (hh, @ Date1, @ Date2). Non è affidabile! Arrotonda in modi imprevedibili

Dato due date ... (le date seguenti: due giorni, tre ore, 10 minuti, 30 secondi di differenza)

declare @Date1 datetime = '2013-03-08 08:00:00' 
declare @Date2 datetime = '2013-03-10 11:10:30' 
declare @Days decimal 
declare @Hours decimal 
declare @Minutes decimal 
declare @Seconds decimal 

select @Days = DATEDIFF(ss,@Date1,@Date2)/60/60/24 --Days 
declare @RemainderDate as datetime = @Date2 - @Days 
select @Hours = datediff(ss, @Date1, @RemainderDate)/60/60 --Hours 
set @RemainderDate = @RemainderDate - (@Hours/24.0) 
select @Minutes = datediff(ss, @Date1, @RemainderDate)/60 --Minutes 
set @RemainderDate = @RemainderDate - (@Minutes/24.0/60) 
select @Seconds = DATEDIFF(SS, @Date1, @RemainderDate)  
select @Days as ElapsedDays, @Hours as ElapsedHours, @Minutes as ElapsedMinutes, @Seconds as ElapsedSeconds 
0

Spero che questo ti aiuta a ottenere il tempo esatto tra due marche temporali

Create PROC TimeDurationbetween2times(@iTime as time,@oTime as time) 
As 
Begin 

DECLARE @Dh int, @Dm int, @Ds int ,@Im int, @Om int, @Is int,@Os int  

SET @Im=DATEPART(MI,@iTime) 
SET @Om=DATEPART(MI,@oTime) 
SET @Is=DATEPART(SS,@iTime) 
SET @Os=DATEPART(SS,@oTime) 

SET @Dh=DATEDIFF(hh,@iTime,@oTime) 
SET @Dm = DATEDIFF(mi,@iTime,@oTime) 
SET @Ds = DATEDIFF(ss,@iTime,@oTime) 

DECLARE @HH as int, @MI as int, @SS as int 

if(@Im>@Om) 
begin 
SET @[email protected] 
end 
if(@Is>@Os) 
begin 
SET @[email protected] 
end 

SET @HH = @Dh 
SET @MI = @Dm-(60*@HH) 
SET @SS = @Ds-(60*@Dm) 

DECLARE @hrsWkd as varchar(8)   

SET @hrsWkd = cast(@HH as char(2))+':'+cast(@MI as char(2))+':'+cast(@SS as char(2))   

select @hrsWkd as TimeDuration 

End 
2
DECLARE @EndTime AS DATETIME, @StartTime AS DATETIME 

SELECT @StartTime = '2013-03-08 08:00:00', @EndTime = '2013-03-08 08:30:00' 

SELECT CAST(@EndTime - @StartTime AS TIME) 

dei risultati: 00:30:00.0000000

Formato risultato come meglio credi.

+0

Funziona solo in SQL Server 2008+, ma è un'ottima soluzione presumendo che sia possibile garantire la versione. –

+0

Fallirà se il tempo è maggiore di 24 ore – Dave

1

Il modo migliore e semplice:

Convert(varchar, {EndTime} - {StartTime}, 108) 

Proprio come Anri notato.

1

Utilizzare il DATEDIFF al valore di ritorno in millisecondi, secondi, minuti, ore, ...

DATEDIFF (intervallo, date1, date2)

intervalloNECESSARIA - L'ora/data parte ritornare. Può essere uno dei seguenti valori:

year, yyyy, yy = Year 
quarter, qq, q = Quarter 
month, mm, m = month 
dayofyear = Day of the year 
day, dy, y = Day 
week, ww, wk = Week 
weekday, dw, w = Weekday 
hour, hh = hour 
minute, mi, n = Minute 
second, ss, s = Second 
millisecond, ms = Millisecond 

date1, date2RICHIESTO - Le due date per calcolare la differenza tra

Problemi correlati