Подтвердить что ты не робот

Получение секунд между двумя Oracle Timestamps

Tom Kyte предлагает использовать EXTRACT для получите разницу:

extract( day from (x-y) )*24*60*60+
extract( hour from (x-y) )*60*60+
...

Кажется, что труднее читать и медленнее, чем это, например:

( CAST( x AS DATE ) - CAST( y AS DATE ) ) * 86400

Итак, каков способ получить разницу между двумя отметками времени в секундах? Спасибо!

4b9b3361

Ответ 1

"Лучшая практика"

Что бы вы ни делали, оберните его в функцию, например. seconds_between (from_date, to_date) - не имеет значения, как он это делает (выберите наиболее эффективный метод) - тогда будет совершенно очевидно, что делает ваш код.

Производительность

Я протестировал два метода на 11gR1 на своем ноутбуке (WinXP) с тестовым примером ниже. Кажется, что опция CAST самая быстрая. (t1 - базовая линия, t2 - метод extract, t3 - метод cast)

t1 (nothing) 3
t2 (extract) 338
t3 (cast)    101

t1 (nothing) 3
t2 (extract) 336
t3 (cast)    100

Тест script

declare
 x TIMESTAMP := SYSTIMESTAMP;
 y TIMESTAMP := TRUNC(SYSDATE);
 n PLS_INTEGER;
 lc CONSTANT PLS_INTEGER := 1000000;
 t1 PLS_INTEGER;
 t2 PLS_INTEGER;
 t3 PLS_INTEGER;
begin
 t1 := DBMS_UTILITY.get_time;
 for i in 1..lc loop
  n := i;
 end loop;
 t1 := DBMS_UTILITY.get_time - t1;
 t2 := DBMS_UTILITY.get_time;
 for i in 1..lc loop
  n := extract(day from (x-y))*24*60*60
     + extract(hour from (x-y))*60*60
     + extract(minute from (x-y))*60
     + extract(second from (x-y));
 end loop;
 t2 := DBMS_UTILITY.get_time - t2;
 t3 := DBMS_UTILITY.get_time;
 for i in 1..lc loop
  n := ( CAST( x AS DATE ) - CAST( y AS DATE ) ) * 86400;
 end loop;
 t3 := DBMS_UTILITY.get_time - t3;
 dbms_output.put_line('t1 (nothing) ' || t1);
 dbms_output.put_line('t2 (extract) ' || t2);
 dbms_output.put_line('t3 (cast)    ' || t3);
end;

Ответ 2

Альтернатива:
Я нашел, что это тоже работает, чтобы получить разницу в секундах, включая миллисекунды.
Он даже экономит время-зоны с "летним днем", в то время как метод extract будет иметь проблему. К сожалению, разница между t1 и t2 ограничена, чтобы результат был правильным. Формат времени от даты до даты не является вариантом, потому что теряются доли секунд.

select (sysdate + (t2 - t1)*1000 - sysdate) * 86.4 from 
(select  
    to_timestamp('2014-03-30 01:00:10.111','YYYY-MM-DD HH24:MI:SS.FF') at time zone 'MET' t1, 
    to_timestamp('2014-03-30 03:00:10.112','YYYY-MM-DD HH24:MI:SS.FF') at time zone 'MET' t2 
 from dual);

Ответ 3

Я всегда использовал второй способ, то есть сравните DATE (что дает вам разницу в днях с дробной частью) и умножьте на коэффициент, который вы хотите дать вам количество часов, минут, секунд или что угодно.

Я думаю, что это хорошо и легко читать.

Ответ 4

Лично я нахожу:

extract(day from (x-y))*24*60*60 + ... + extract(second from (x-y))

понятнее, чем...

( CAST( x AS DATE ) - CAST( y AS DATE ) ) * 86400

чтобы получить разницу в секундах.

Метод Tom принимает еще несколько нажатий клавиш, но цель понятна.

Ответ 5

для быстрого и удобного использования:

extract( day from(t2 - t1)*24*60*60)

Пример:

with dates as (
   select
        to_timestamp('2019-06-18 22:50:00', 'yyyy-mm-dd hh24:mi:ss') t1
      , to_timestamp('2019-06-19 00:00:38', 'yyyy-mm-dd hh24:mi:ss') t2
   from dual
)
select
    extract( day from(t2 - t1)*24*60*60) diff_in_seconds
from dates
;

Выход:

DIFF_IN_SECONDS
---------------
            638

Ответ 6

to_number(to_char(t2, 'yyyymmddhh24missff')) - to_number(to_char(t1, 'yyyymmddhh24missff'))