Oracle
 sql >> Base de données >  >> RDS >> Oracle

Résultat du format de soustraction de temps

Lorsque vous soustrayez un horodatage d'un autre, le résultat est un type de données d'intervalle interne, mais vous pouvez le traiter comme un "intervalle de jour à seconde" :

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

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

Le '+08' (dans mon fuseau horaire de session) est le nombre de jours, pas un décalage UTC ; c'est la valeur car lorsque vous convertissez une chaîne en date ou en horodatage et ne fournissez que la partie heure, la partie date par défaut est le premier jour du mois en cours :

Les valeurs de date par défaut sont déterminées comme suit :

  • L'année est l'année en cours, telle que renvoyée par SYSDATE.
  • Le mois est le mois en cours, tel que renvoyé par SYSDATE.
  • Le jour est 01 (le premier jour du mois).
  • L'heure, la minute et la seconde valent toutes 0.

Ces valeurs par défaut sont utilisées dans une requête qui demande des valeurs de date où la date elle-même n'est pas spécifiée...

Donc je compare vraiment :

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

Vous ne pouvez pas formater directement un intervalle, mais vous pouvez extraire les éléments de l'heure et les formater séparément, puis les concaténer.

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

Le calcul répété du même intervalle semble un peu inutile et difficile à gérer, vous pouvez donc le faire dans une vue en ligne ou 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

Vous pouvez également utiliser des dates au lieu d'horodatages ; la soustraction vous donne alors la différence sous forme de nombre, avec des jours entiers et fractionnaires :

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

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

La façon la plus simple de formater cela est de l'ajouter à une heure de minuit connue, puis d'utiliser 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

Je suis resté avec current_date comme la correspondance la plus proche de localtimestamp; vous voudrez peut-être en fait systimestamp et/ou sysdate . (Plus d'informations sur la différence ici.)