Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Resultado do formato de subtração de tempo


Quando você subtrai um carimbo de data/hora de outro, o resultado é um tipo de dados de intervalo interno, mas você pode tratá-lo como 'intervalo de dia para segundo':
select
(localtimestamp - to_timestamp(us.STARTDATETIME,'hh24:mi:ss')) as HoursPassed
from random us;

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

O '+08' (no fuso horário da minha sessão) é o número de dias, não um deslocamento UTC; esse é o valor porque quando você converte uma string em uma data ou timestamp e fornece apenas a parte da hora, a parte da data é padronizada para o primeiro dia do mês atual:

Os valores de data padrão são determinados da seguinte forma:
  • O ano é o ano atual, conforme retornado por SYSDATE.
  • O mês é o mês atual, conforme retornado por SYSDATE.
  • O dia é 01 (o primeiro dia do mês).
  • A hora, o minuto e o segundo são todos 0.

Esses valores padrão são usados ​​em uma consulta que solicita valores de data em que a própria data não é especificada ...

Então estou realmente 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

Você não pode formatar um intervalo diretamente, mas pode extrair os elementos do tempo e formatá-los separadamente e concatená-los.
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 o mesmo intervalo parece um pouco inútil e difícil de gerenciar, então você pode fazer isso em uma visualização em linha ou em um 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

Você também pode usar datas em vez de carimbos de data/hora; a subtração fornece a diferença como um número, com dias inteiros e fracionários:
select current_date - to_date(us.STARTDATETIME, 'hh24:mi') as hourspassed
from random us;

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

A maneira mais simples de formatar isso é adicioná-lo a um horário conhecido da meia-noite e 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

Fiquei com current_date como a correspondência mais próxima de localtimestamp; você pode realmente querer systimestamp e/ou sysdate . (Mais sobre a diferença aqui.)