2013-01-21 12 views
9

Potrzebuję obliczyć całkowitą długość pod względem godzin, minut, sekund i średniej długości, biorąc pod uwagę niektóre dane z czasem rozpoczęcia i zakończenia.DATEDIFF w GG: MM: format SS

Na przykład wynik musi być podobny do 45:15:10, co oznacza 45 godzin 15 minut 10 sekund lub 30:07 przez 30 minut 07 sekund.

Używamy SQL Server 2008 R2, a konwersja nie powiodła się, gdy czas przekracza 24:59:59. Masz pomysł, jak to zrobić?

Aby uzyskać więcej informacji, kolumny w tabeli są Id, StartDateTime, EndDateTime itp muszę dokonać miesięczny raport, który zawiera nagrania liczyć od miesiąca, łączna długość tych zapisów i średniej długości. Chciałbym wiedzieć, czy istnieje prosty sposób na wykonanie tego wszystkiego.

+2

Konwertuj wszystko na sekundy, zsumuj, a następnie przekonwertuj do formatu czytelnego ręcznie. – Kermit

Odpowiedz

5

Nie powinieneś konwertować na time - jest przeznaczony do przechowywania punktu w czasie na jednym zegarze 24-godzinnym, a nie czasie trwania ani interwału (nawet tego, który jest ograniczony do siebie przez < 24 godziny, co wyraźnie dane nie są). Zamiast tego możesz pobrać dane w najmniejszym wymaganym interwale (w twoim przypadku, w sekundach), a następnie wykonać kilka operacji na matematyce i łańcuchach, aby przedstawić je w formacie wyjściowym, którego potrzebujesz (może być również wskazane, aby zwrócić sekundy do aplikacji lub narzędzie do raportowania i zlecenie tej pracy).

DECLARE @d TABLE 
(
    id INT IDENTITY(1,1), 
    StartDateTime DATETIME, 
    EndDateTime DATETIME 
); 

INSERT @d(StartDateTime, EndDateTime) VALUES 
(DATEADD(DAY, -2, GETDATE()), DATEADD(MINUTE, 15, GETDATE())), 
(GETDATE()     , DATEADD(MINUTE, 22, GETDATE())), 
(DATEADD(DAY, -1, GETDATE()), DATEADD(MINUTE, 5, GETDATE())), 
(DATEADD(DAY, -4, GETDATE()), DATEADD(SECOND, 14, GETDATE())); 

;WITH x AS (SELECT id, StartDateTime, EndDateTime, 
    d = DATEDIFF(SECOND, StartDateTime, EndDateTime), 
    a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER() 
    FROM @d 
) 
SELECT id, StartDateTime, EndDateTime, 
    [delta_HH:MM:SS] = CONVERT(VARCHAR(5), d/60/60) 
    + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2) 
    + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2), 
    [avg_HH:MM:SS] = CONVERT(VARCHAR(5), a/60/60) 
    + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2) 
    + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2) 
FROM x; 

Wyniki:

id StartDateTime  EndDateTime   delta_HH:MM:SS avg_HH:MM:SS 
-- ------------------- ------------------- -------------- ------------ 
1 2013-01-19 14:24:46 2013-01-21 14:39:46 48:15:00  42:10:33 
2 2013-01-21 14:24:46 2013-01-21 14:46:46 0:22:00  42:10:33 
3 2013-01-20 14:24:46 2013-01-21 14:29:46 24:05:00  42:10:33 
4 2013-01-17 14:24:46 2013-01-21 14:25:00 96:00:14  42:10:33 

To nie jest dokładnie to, co prosiłeś, ponieważ nie pokaże tylko MM: SS dla delt < 1 godzinę. można regulować, które w prosty CASE wyrażeniem:

;WITH x AS (SELECT id, StartDateTime, EndDateTime, 
    d = DATEDIFF(SECOND, StartDateTime, EndDateTime), 
    a = AVG(DATEDIFF(SECOND, StartDateTime, EndDateTime)) OVER() 
    FROM @d 
) 
SELECT id, StartDateTime, EndDateTime, 
    [delta_HH:MM:SS] = CASE WHEN d >= 3600 THEN 
    CONVERT(VARCHAR(5), d/60/60) + ':' ELSE '' END 
    + RIGHT('0' + CONVERT(VARCHAR(2), d/60%60), 2) 
    + ':' + RIGHT('0' + CONVERT(VARCHAR(2), d % 60), 2), 
    [avg_HH:MM:SS] = CASE WHEN a >= 3600 THEN 
    CONVERT(VARCHAR(5), a/60/60) + ':' ELSE '' END 
    + RIGHT('0' + CONVERT(VARCHAR(2), a/60%60), 2) 
    + ':' + RIGHT('0' + CONVERT(VARCHAR(2), a % 60), 2) 
FROM x; 

Zapytanie zmienia kolumnę delta 2. rzędzie w powyższym związku z 0:22:00 do 22:00.

1

Jeśli chcesz uśredniać, najlepszym sposobem jest konwersja na sekundy lub ułamki dnia. frakcje dziennie są wygodne w SQL Server, ponieważ można robić takie rzeczy jak:

select avg(cast(endtime - starttime) as float) 
from t 

można przekonwertować go z powrotem do datetime stosując odwrotną Obsada:

select cast(avg(cast(endtime - starttime as float) as datetime) 
from t 

arytmetycznej uzyskać razy w format, który chcesz. . . to jest ból. Można rozważyć łącznie dni w ostatecznej formie i przy użyciu:

select right(convert(varchar(255), <val>, 120), 10) 

Aby uzyskać godzin przekraczającym 24, tutaj jest inne podejście:

select cast(floor(cast(<val> as float)*24) as varchar(255))+right(convert(varchar(255), <val>, 120), 6) 

Wykorzystuje convert na minuty i sekundy, które powinny być wyściełane 0s po lewej. Następnie dodaje godziny jako oddzielną wartość.

4
SELECT CONVERT(time, 
       DATEADD(mcs, 
         DATEDIFF(mcs, 
           '2007-05-07 09:53:00.0273335', 
           '2007-05-07 09:53:01.0376635'), 
         CAST('1900-01-01 00:00:00.0000000' as datetime2) 
        ) 
      ) 
0

Ja nieznacznie zmodyfikowałem odpowiedź Avinasha, ponieważ może zakończyć się błędem, jeśli różnica jest zbyt duża.Jeśli potrzebujesz tylko HH: mm: ss, wystarczy rozróżnić na poziomie sekund w następujący sposób:

SELECT CONVERT(time, 
    DATEADD(s, 
    DATEDIFF(s, 
     '2018-01-07 09:53:00', 
     '2018-01-07 11:53:01'), 
    CAST('1900-01-01 00:00:00.0000000' as datetime2) 
    ) 
) 
Powiązane problemy