Oracle
 sql >> Database >  >> RDS >> Oracle

Risultato del formato di sottrazione del tempo

Quando sottrai un timestamp da un altro, il risultato è un tipo di dati di intervallo interno, ma puoi considerarlo come "intervallo da giorno a secondo":

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

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

Il "+08" (nel mio fuso orario della sessione) è il numero di giorni, non un offset UTC; questo è il valore perché quando si converte una stringa in una data o in un timestamp e si fornisce solo la parte dell'ora, la parte della data viene impostata automaticamente sul primo giorno del mese corrente:

I valori di data predefiniti sono determinati come segue:

  • L'anno è l'anno corrente, come restituito da SYSDATE.
  • Il mese è il mese corrente, come restituito da SYSDATE.
  • Il giorno è 01 (il primo giorno del mese).
  • L'ora, i minuti ei secondi sono tutti 0.

Questi valori predefiniti vengono utilizzati in una query che richiede valori di data in cui la data stessa non è specificata ...

Quindi sto davvero confrontando:

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

Non puoi formattare direttamente un intervallo, ma puoi estrarre gli elementi dell'ora e formattarli separatamente e concatenarli.

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

Il calcolo ripetuto dello stesso intervallo sembra un po' dispendioso e difficile da gestire, quindi puoi farlo in una visualizzazione in linea o in un 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

Potresti anche usare le date invece dei timestamp; la sottrazione quindi ti dà la differenza come numero, con giorni interi e frazionari:

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

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

Il modo più semplice per formattarlo è aggiungerlo a un'ora di mezzanotte nota e quindi utilizzare to_char() :

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

Sono rimasto bloccato con current_date come corrispondenza più vicina a localtimestamp; potresti effettivamente volere systimestamp e/o sysdate . (Ulteriori informazioni sulla differenza qui.)