Wanneer u de ene tijdstempel van de andere aftrekt, is het resultaat een intern intervalgegevenstype, maar u kunt het behandelen als 'interval van dag tot seconde':
select
(localtimestamp - to_timestamp(us.STARTDATETIME,'hh24:mi:ss')) as HoursPassed
from random us;
HOURSPASSED
-------------------
+08 15:26:54.293892
De '+08' (in mijn sessietijdzone) is het aantal dagen, geen UTC-offset; dat is de waarde die het is, want wanneer u een tekenreeks converteert naar een datum of tijdstempel en alleen het tijdgedeelte opgeeft, wordt het datumgedeelte standaard ingesteld op de eerste dag van de huidige maand:
De standaard datumwaarden worden als volgt bepaald:
- Het jaar is het huidige jaar, zoals teruggegeven door SYSDATE.
- De maand is de huidige maand, zoals geretourneerd door SYSDATE.
- De dag is 01 (de eerste dag van de maand).
- Het uur, de minuut en de seconde zijn allemaal 0.
Deze standaardwaarden worden gebruikt in een query die om datumwaarden vraagt waarbij de datum zelf niet is opgegeven ...
Dus ik ben echt aan het vergelijken:
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
U kunt een interval niet direct opmaken, maar u kunt de elementen van de tijd extraheren en deze afzonderlijk formatteren en samenvoegen.
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
Herhaaldelijk hetzelfde interval berekenen lijkt een beetje verkwistend en moeilijk te beheren, dus je kunt dat doen in een inline-weergave of een CTE:
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
U kunt ook datums gebruiken in plaats van tijdstempels; aftrekken geeft je dan het verschil als een getal, met hele en gebroken dagen:
select current_date - to_date(us.STARTDATETIME, 'hh24:mi') as hourspassed
from random us;
HOURSPASSED
-----------
8.64368056
De eenvoudigste manier om dat te formatteren is door het toe te voegen aan een bekende middernachttijd en vervolgens to_char()
te gebruiken :
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
Ik blijf bij current_date
als de beste overeenkomst met localtimestamp
; misschien wil je eigenlijk systimestamp
en/of sysdate
. (Meer over het verschil hier.)