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

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

При вычитании timestamps возвращаемое значение представляет собой тип данных interval. Есть ли элегантный способ преобразования этого значения в общее число (милли/микро) секунд в интервале, т.е. Целое число.

Следующие действия будут работать, но это не очень красиво:

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 )

Есть ли более элегантный метод в SQL или PL/SQL?

4b9b3361

Ответ 1

Я надеюсь, что эта помощь:

[email protected]> 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

С тестом:

[email protected]> 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

[email protected]> 

Ответ 2

Простой способ:

select extract(day from (ts1-ts2)*86400) from dual;

Идея состоит в том, чтобы преобразовать значение интервала в дни по времени 86400 (= 24 * 60 * 60). Затем извлеките значение "день", которое фактически является вторым значением, которое мы хотели.

Ответ 3

Я нашел, что это работает. Видимо, если вы делаете арифметику с отметками времени, они преобразуются в некоторый внутренний тип данных, которые при вычитании друг из друга возвращают интервал как число.

Легко? Да. Элегантный? Нет. Выполняет работу? О да.

SELECT ( (A + 0) - (B + 0) ) * 24 * 60 * 60 
FROM
(
   SELECT SYSTIMESTAMP A,
          SYSTIMESTAMP - INTERVAL '1' MINUTE B
   FROM DUAL
);

Ответ 4

К сожалению, я не думаю, что есть альтернативный (или более элегантный) способ вычисления общего количества секунд из типа интервала в pl/sql. эта статья упоминает:

... unlike .NET, Oracle provides no simple equivalent to TimeSpan.TotalSeconds.

поэтому извлечение дня, часа и т.д. из интервала и умножение их на соответствующие значения кажется единственным способом.

Ответ 5

Основываясь на zep answer, я сделал все для удобства:

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 ; 

Ответ 6

Используйте следующий запрос:

select (cast(timestamp1 as date)-cast(timestamp2 as date))*24*60*60)

Ответ 7

Аналогично ответу @Zhaoping Lu, но непосредственно извлекает секунды вместо того, чтобы получать их из числа дней.

SELECT extract(second from (end_date - start_date)) as "Seconds number"
FROM my_table

(работал на PostgresSQL 9.6.1)

Ответ 8

ВЫБЕРИТЕ to_char (ENDTIME, 'ггггммдчh24missff') -to_char (STARTTIME, 'ггггммддх24missff') как DUR ОТ ДВОЙНОГО; yyyymmddhh24miss- ДАЕТ ДЛИТЕЛЬНОСТЬ В СЕКУНДУ yyyymmddhh24mi DURATION IN MIN yyyymmddhh24 - ПРОДОЛЖИТЕЛЬНОСТЬ - ЧАСЫ yyyymmdd ПРОДОЛЖИТЕЛЬНОСТЬ В ДНЯХ