sql >> Base de Datos >  >> RDS >> Oracle

Resultado del formato de resta de tiempo

Cuando resta una marca de tiempo de otra, el resultado es un tipo de datos de intervalo interno, pero puede tratarlo como 'intervalo día a segundo':

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

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

El '+08' (en la zona horaria de mi sesión) es el número de días, no un desplazamiento UTC; ese es el valor porque cuando convierte una cadena en una fecha o marca de tiempo y solo proporciona la parte de la hora, la parte de la fecha se establece de forma predeterminada en el primer día del mes actual:

Los valores de fecha predeterminados se determinan de la siguiente manera:

  • El año es el año actual, tal como lo devuelve SYSDATE.
  • El mes es el mes actual, tal como lo devuelve SYSDATE.
  • El día es 01 (el primer día del mes).
  • La hora, el minuto y el segundo son todos 0.

Estos valores predeterminados se usan en una consulta que solicita valores de fecha donde la fecha en sí no se especifica...

Así que realmente estoy comparando:

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

No puede formatear directamente un intervalo, pero puede extraer los elementos del tiempo y formatearlos por separado y concatenarlos.

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

Calcular repetidamente el mismo intervalo parece un poco inútil y difícil de administrar, por lo que puede hacerlo en una vista en línea o 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

También puede usar fechas en lugar de marcas de tiempo; la resta te da la diferencia como un número, con días enteros y fraccionarios:

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

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

La forma más sencilla de formatear eso es agregarlo a una hora de medianoche conocida y luego usar 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

Me he quedado con current_date como la coincidencia más cercana a localtimestamp; es posible que desee systimestamp y/o sysdate . (Más información sobre la diferencia aquí).