Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Ergebnis des Zeitsubtraktionsformats

Wenn Sie einen Zeitstempel von einem anderen subtrahieren, ist das Ergebnis ein interner Intervalldatentyp, aber Sie können ihn als „Intervall von Tag zu Sekunde“ behandeln:

select
(localtimestamp - to_timestamp(us.STARTDATETIME,'hh24:mi:ss')) as HoursPassed
from random us;

HOURSPASSED        
-------------------
+08 15:26:54.293892

Das '+08' (in meiner Sitzungszeitzone) ist die Anzahl der Tage, kein UTC-Offset; das ist der Wert, denn wenn Sie eine Zeichenfolge in ein Datum oder einen Zeitstempel konvertieren und nur den Zeitteil angeben, wird der Datumsteil standardmäßig auf den ersten Tag des aktuellen Monats gesetzt:

Die Standard-Datumswerte werden wie folgt bestimmt:

  • Das Jahr ist das aktuelle Jahr, wie es von SYSDATE zurückgegeben wird.
  • Der Monat ist der aktuelle Monat, wie er von SYSDATE zurückgegeben wird.
  • Der Tag ist 01 (der erste Tag des Monats).
  • Stunde, Minute und Sekunde sind alle 0.

Diese Standardwerte werden in einer Abfrage verwendet, die Datumswerte anfordert, bei denen das Datum selbst nicht angegeben ist ...

Ich vergleiche also wirklich:

select localtimestamp, to_timestamp(us.STARTDATETIME,'hh24:mi:ss')
from random us;

LOCALTIMESTAMP             TO_TIMESTAMP(US.STARTDATET
-------------------------- --------------------------
2017-08-09 23:26:54.293892 2017-08-01 08:00:00.000000

Sie können ein Intervall nicht direkt formatieren, aber Sie können die Elemente der Zeit extrahieren und diese separat formatieren und verketten.

select to_char(extract(hour from (localtimestamp
    - to_timestamp(us.STARTDATETIME, 'hh24:mi:ss'))), 'FM00')
  ||':'|| to_char(extract(minute from (localtimestamp
    - to_timestamp(us.STARTDATETIME, 'hh24:mi:ss'))), 'FM00')
  ||':'|| to_char(extract(second from (localtimestamp
    - to_timestamp(us.STARTDATETIME, 'hh24:mi:ss'))), 'FM00')
  as hourspassed
from random us;

HOURSPASSED
-----------
15:26:54

Das wiederholte Berechnen des gleichen Intervalls sieht etwas verschwenderisch und schwer zu handhaben aus, also können Sie das in einer Inline-Ansicht oder einem CTE tun:

with cte (diff) as (
  select localtimestamp - to_timestamp(us.STARTDATETIME, 'hh24:mi:ss')
  from random us
)
select to_char(extract(hour from diff), 'FM00')
  ||':'|| to_char(extract(minute from diff), 'FM00')
  ||':'|| to_char(extract(second from diff), 'FM00')
  as hourspassed
from cte;

HOURSPASSED
-----------
15:26:54

Sie können auch Datumsangaben anstelle von Zeitstempeln verwenden; Die Subtraktion gibt Ihnen dann die Differenz als Zahl mit ganzen und angebrochenen Tagen:

select current_date - to_date(us.STARTDATETIME, 'hh24:mi') as hourspassed
from random us;

HOURSPASSED
-----------
 8.64368056

Der einfachste Weg, dies zu formatieren, besteht darin, es zu einer bekannten Mitternachtszeit hinzuzufügen und dann to_char() zu verwenden :

select to_char(date '1970-01-01'
  + (current_date - to_date(us.STARTDATETIME, 'hh24:mi')),
  'HH24:MI:SS') as hourspassed
from random us;

HOURSPAS
--------
15:26:54

Ich bin bei current_date geblieben als die engste Übereinstimmung mit localtimestamp; Sie möchten vielleicht systimestamp und/oder sysdate . (Mehr zum Unterschied hier.)