2012-12-13 7 views
10

Mam SQL Server tabeli, która ma kolumnę "Czas". Tabela jest tabelą dziennika komunikatów o stanie domów i sygnatur czasowych dla każdej wiadomości. Tabela dziennika jest wstawiana do pliku wsadowego. Istnieje kolumna ID, która grupuje wiersze. Za każdym razem, gdy uruchamiany jest plik wsadowy, inicjuje identyfikator i zapisuje rekordy. To, co muszę zrobić, to uzyskać czas, jaki upłynął od pierwszego rekordu w zestawie identyfikatorów do ostatniego rekordu tego samego zestawu identyfikatorów. Zacząłem żartować z wybieraniem Max (Czas) - Min (Czas) z logTable, gdzie id = ale nie mogłem wymyślić jak poprawnie go sformatować. Potrzebuję go w GG: MM: SS.Serwer SQL - oblicz czas, jaki upłynął między dwoma datetime stemple w GG: MM: SS format

+0

Daj nam znać typ danych w kolumnie „Time”. DateTime, DateTime2, Time, Timestamp, itp. –

+0

@Tim ... mój zły, DateTime – MikeTWebb

Odpowiedz

8

SQL Server nie obsługuje standardowego typu danych interwału SQL. Najlepiej jest obliczyć różnicę w sekundach i użyć funkcji do sformatowania wyniku. Natywna funkcja CONVERT() może wydawać się działać dobrze , o ile twój interwał jest krótszy niż 24 godziny. Ale CONVERT() nie jest dobrym rozwiązaniem.

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

Wartości zostały wybrane w taki sposób, że

  • id = 1 Upływający czas 1 godziny
  • id = 2, który upłynął czas 2 godzin, a
  • id = 3, upływ czasu wynosi 3 godziny.

Ta instrukcja SELECT zawiera jedną kolumnę, która oblicza sekundy, i jedną, która używa funkcji CONVERT() z odejmowaniem.

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 

Uwaga wprowadzająca w błąd "03:00:00" różnicy 27-godzinny numer id 3.

Function to format elapsed time in SQL Server

+0

@Catcall .... pytanie: zapytanie zadziałało dla tych dwóch dat, które obejmowały dwa dni (2012-12-13 15: 10: 12.050 i 2012-12-12 20: 16: 47.160). Twoje wyniki to 68005 sekund i 18:53:24. Wygląda to dobrze. Nie wiesz, dlaczego jest do not_not_use 18:53:24? – MikeTWebb

+1

Funkcja CONVERT() zwraca błędną odpowiedź w odstępach czasu w ciągu 24 godzin. Różnica między tymi dwoma znacznikami czasu wynosi mniej niż 24 godziny. Kolumna "do_not_use" ma zniechęcić użytkownika do używania funkcji CONVERT() do formatowania interwałów. –

+0

@Catcall ... tak, rozumiem znaczenie kolumny "do_not_use". Byłem ciekawy CONVERT() .... a twoje wyjaśnienie jest idealne. Dzięki! – MikeTWebb

0

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

+0

Wyjdzie "03:00:00" dla 27-godzinnej różnicy między dwoma sygnaturami czasowymi ... – XpiritO

8

AKTUALIZACJA:

poprawnie obliczyć przedział czasu w SQL Server, nawet jeśli więcej niż 24 godzin: Szafy

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

brzegowe, które pokazują niedokładności są szczególnie mile widziane!

+0

@Tim .... to prawie działa. W przypadku tych dwóch dat (2012-12-13 15: 10: 12.050 i 2012-12-12 20: 16: 47.160) zapytanie zwróciło wynik 19:54:25, gdy rzeczywista wartość to 18:53:24. Pomysły? – MikeTWebb

+0

@MikeTWebb może się okazać, że obecna wersja działa dobrze, jeśli nie chcesz korzystać z funkcji lub jest ograniczona w ilu godzinach można reprezentować. –

1

Zobacz, czy to pomaga. Mogę ustawić zmienne dla Elapsed Days, Hours, Minutes, Seconds. Możesz sformatować to zgodnie ze swoimi upodobaniami lub zawrzeć w funkcji zdefiniowanej przez użytkownika.

Uwaga: nie należy używać DateDiff (hh, @ Date1, @ Date2). To nie jest niezawodne! Rozgrywa się w nieprzewidywalny sposób

Biorąc pod uwagę dwie daty ... (próbka Terminy: dwa dni, trzy godziny, 10 minut, 30 difference sekund)

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

nadzieję, że to pomaga w uzyskaniu dokładnego czasu pomiędzy dwoma znacznikami czasu

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) 

Rezultatów: 00:30:00.0000000

Wynik formatu zgodny z Twoim opisem.

+0

Działa to tylko w SQL Server 2008+, ale jest to świetne rozwiązanie, zakładając, że możesz zagwarantować wersję. –

+0

Zepsuje się, jeśli czas przekroczy 24 godziny – Dave

1

Najlepszy i prosty sposób:

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

Podobnie jak Anri zauważyć.

1

pomocą DATEDIFF powrotu wartość w milisekundach, sekundy, minuty, godziny, ...

DATEDIFF (przedział, date1, data2)

przedziałWYMAGANY - Czas/data część wracać. Może być jedną z następujących wartości:

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, date2WYMAGANE - Te dwie daty, aby obliczyć różnicę między

Powiązane problemy