Lors de la soustraction de timestamps
, la valeur de retour est un type de données interval
. Existe-t-il un moyen élégant de convertir cette valeur en nombre total (milli/micro) secondes dans l'intervalle, c'est-à-dire un entier.
Ce qui suit fonctionnerait, mais ce n'est pas très joli:
select abs( extract( second from interval_difference )
+ extract( minute from interval_difference ) * 60
+ extract( hour from interval_difference ) * 60 * 60
+ extract( day from interval_difference ) * 60 * 60 * 24
)
from ( select systimestamp - (systimestamp - 1) as interval_difference
from dual )
Existe-t-il une méthode plus élégante en SQL ou PL/SQL?
J'espère que cette aide:
zep@dev> select interval_difference
2 ,sysdate + (interval_difference * 86400) - sysdate as fract_sec_difference
3 from (select systimestamp - (systimestamp - 1) as interval_difference
4 from dual)
5 ;
INTERVAL_DIFFERENCE FRACT_SEC_DIFFERENCE
------------------------------------------------------------------------------- --------------------
+000000001 00:00:00.375000 86400,375
Avec votre test:
zep@dev> select interval_difference
2 ,abs(extract(second from interval_difference) +
3 extract(minute from interval_difference) * 60 +
4 extract(hour from interval_difference) * 60 * 60 +
5 extract(day from interval_difference) * 60 * 60 * 24) as your_sec_difference
6 ,sysdate + (interval_difference * 86400) - sysdate as fract_sec_difference
7 ,round(sysdate + (interval_difference * 86400) - sysdate) as sec_difference
8 ,round((sysdate + (interval_difference * 86400) - sysdate) * 1000) as millisec_difference
9 from (select systimestamp - (systimestamp - 1) as interval_difference
10 from dual)
11 /
INTERVAL_DIFFERENCE YOUR_SEC_DIFFERENCE FRACT_SEC_DIFFERENCE SEC_DIFFERENCE MILLISEC_DIFFERENCE
------------------------------------------------------------------------------- ------------------- -------------------- -------------- -------------------
+000000001 00:00:00.515000 86400,515 86400,515 86401 86400515
zep@dev>
Un moyen simple:
select extract(day from (ts1-ts2)*86400) from dual;
L'idée est de convertir la valeur de l'intervalle en jours par fois 86400 (= 24 * 60 * 60). Ensuite, extrayez la valeur "jour" qui est en fait la deuxième valeur que nous voulions.
J'ai trouvé que ça fonctionnait. Apparemment, si vous faites des calculs avec des horodatages, ils sont convertis en un type de données interne qui, une fois soustrait les uns des autres, renvoie l'intervalle sous forme de nombre.
Facile? Oui. Élégant? Non. Fait le travail? Oh oui.
SELECT ( (A + 0) - (B + 0) ) * 24 * 60 * 60
FROM
(
SELECT SYSTIMESTAMP A,
SYSTIMESTAMP - INTERVAL '1' MINUTE B
FROM DUAL
);
Malheureusement, je ne pense pas qu'il existe une manière alternative (ou plus élégante) de calculer le nombre total de secondes à partir d'un type d'intervalle en pl/sql. Comme cet article mentionne:
... unlike .NET, Oracle provides no simple equivalent to TimeSpan.TotalSeconds.
par conséquent, extraire le jour, l'heure, etc. de l'intervalle et les multiplier par des valeurs correspondantes semble être le seul moyen.
Basé sur réponse de zep , j'ai enveloppé les choses dans une fonction pour votre commodité:
CREATE OR REPLACE FUNCTION intervalToSeconds(
pMinuend TIMESTAMP , pSubtrahend TIMESTAMP ) RETURN NUMBER IS
vDifference INTERVAL DAY TO SECOND ;
vSeconds NUMBER ;
BEGIN
vDifference := pMinuend - pSubtrahend ;
SELECT EXTRACT( DAY FROM vDifference ) * 86400
+ EXTRACT( HOUR FROM vDifference ) * 3600
+ EXTRACT( MINUTE FROM vDifference ) * 60
+ EXTRACT( SECOND FROM vDifference )
INTO
vSeconds
FROM DUAL ;
RETURN vSeconds ;
END intervalToSeconds ;
Utilisez la requête suivante:
select (cast(timestamp1 as date)-cast(timestamp2 as date))*24*60*60)