2014-01-13 18 views
7

Ich brauche die Differenz zwischen der Zeit im Format hh zu finden: mm: ssfinden die verstrichene Zeit zwischen zwei Daten in Oracle SQL

select msglog.id,max(msglog.timestamp) enddate, 
    min(msglog.timestamp) startdate, 
    enddate - startdate 
    from MESSAGELOG msglog 
    group by id 

Im abovequery msglog.timestamp ist vom Typ DATE.

Wie kann ich die verstrichene Zeit oder Differenz zwischen der Uhrzeit im richtigen Format in Oracle erhalten?

Antwort

12

Datumsarithmetik in Oracle ergibt eine Zahl in Tagen. Also, um Stunden zu konvertieren, würden Sie mit 24 multiplizieren und dann trunc eine ganze Zahl zu erhalten:

trunc(24 * (enddate - startdate)) 

Minuten zu erhalten, wandeln die Tage Wert auf Minuten und mod(), dass mit 60:

mod(trunc(24 * 60 * (enddate - startdate)), 60) 

Für Sekunden konvertieren wieder Tage auf Sekunden und mod(), dass mit 60:

mod(trunc(24 * 60 * 60 * (enddate - startdate)), 60) 

Jetzt können Sie diese zusammen den String-Wert bekommen Sie ne ed.

+0

Danke für die upvote @GriffeyDog verwenden können, und ein sich selbst! Ihre Antwort wird auch gut funktionieren. Es kommt auf viele Mathe im Vergleich zu vielen Funktionsaufrufen, und ich erwarte, dass einige Leute mit viel Mathe wohler sein können. –

17

Wenn Sie zwei DATE Werte wie enddate - startdate subtrahieren, erhalten Sie die Differenz in Tagen mit dezimaler Genauigkeit, also zum Beispiel 1,5 würde 1 1/2 Tage oder 36 Stunden bedeuten. Sie können das zu HH:MI:SS konvertieren eine Menge Mathematik verwenden, aber ein einfacher Weg ist, den Dezimalwert auf einen INTERVAL DAY TO SECOND Wert mit der NUMTODSINTERVAL Funktion zu konvertieren:

NUMTODSINTERVAL(enddate - startdate, 'DAY') 

Man könnte meinen, die TO_CHAR Funktion zur Formatierung der Lage wäre, dies als HH:MI:SS, aber es scheint nicht so zu funktionieren. Sie können EXTRACT stattdessen verwenden, und TO_CHAR um sicherzustellen, dass Sie führende Nullen erhalten:

TO_CHAR(EXTRACT(HOUR FROM NUMTODSINTERVAL(enddate-startdate, 'DAY')), 'FM00') 
    || ':' || 
TO_CHAR(EXTRACT(MINUTE FROM NUMTODSINTERVAL(enddate-startdate, 'DAY')), 'FM00') 
    || ':' || 
TO_CHAR(EXTRACT(SECOND FROM NUMTODSINTERVAL(enddate-startdate, 'DAY')), 'FM00') 

Der 00 Teil des Formatcode gibt an zwei Stellen, mit einer führenden Null, wenn nötig. Der FM-Teil löscht den führenden Platz im formatierten Ergebnis, das bei Bedarf für ein negatives Vorzeichen reserviert ist.

Beachten Sie auch, dass Ihre Abfrage Aggregatwerte erhält und in der gleichen SELECT Liste verwendet. Oracle lässt dich das nicht tun. Versuchen Sie so etwas wie dieses stattdessen:

WITH StartEndByID AS (
    SELECT 
    msglog.id, 
    NUMTODSINTERVAL(max(msglog.timestamp) - min(msglog.timestamp), 'DAY') elapsed 
    FROM messagelog msglog 
    GROUP BY id 
) 
SELECT 
    id, 
    TO_CHAR(EXTRACT(HOUR FROM elapsed), 'FM00') || ':' || 
    TO_CHAR(EXTRACT(MINUTE FROM elapsed), 'FM00') || ':' || 
    TO_CHAR(EXTRACT(SECOND FROM elapsed), 'FM00') AS ElapsedHHMISS 
FROM StartEndByID 
+0

Ich mag das besser als meine Antwort, +1. – GriffeyDog

+0

Hi Ed, nur neugierig zu wissen, ob NUMTODSINTERVAL für Timestamp Intervalle funktioniert? – San

+0

@San - das Ergebnis von [timestamp arithmetic] (http://docs.oracle.com/cd/E11882_01/server.112/e26088/sql_elements001.htm#SQLRF50990) ist sowieso ein 'Intervall', also nicht müssen Sie es in eins umwandeln. –

1

Um die diff in Sekunden erhalten Sie diese

select round(24 * 60 * 60* (TO_DATE('2017/02/17 9:32:25', 'YYYY/MM/DD HH:MI:SS') - TO_DATE('2017/02/17 8:30:30', 'YYYY/MM/DD HH:MI:SS'))) from dual; 
Verwandte Themen