programing

간격 데이터 유형에서 총 초수 추출

telebox 2023. 4. 2. 10:18
반응형

간격 데이터 유형에서 총 초수 추출

빼는 경우timestamps반환값은intervaldata-이 값을 인터벌의 합계(밀리/마이크로) 초수(정수)로 변환하는 우아한 방법이 있습니까?

다음과 같은 방법이 효과적이지만 그다지 예쁘지는 않습니다.

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에서 보다 우아한 방법이 있습니까?

간단한 방법:

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

이 방법은 간격 값을 86400(= 24*60*60)의 곱으로 변환하는 것입니다.그런 다음 실제로 원하는 두 번째 값인 '일' 값을 추출합니다.

도움이 되었으면 합니다.

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

테스트 시:

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> 

이게 효과가 있다는 걸 알았어요.분명히 타임스탬프를 사용하여 산술적으로 계산하면 타임스탬프는 내부 데이터형으로 변환되며, 이 데이터형은 서로 부분집약하면 간격은 숫자로 반환됩니다.

쉬워요? 네, 우아해요?아니, 일은 다 끝냈나?오, 그래.

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

유감스럽게도, pl/sql의 인터벌 타입으로부터 합계 초수를 계산하는 다른 방법(또는 보다 우아한 방법)은 없다고 생각합니다. 기사에 기재된 바와 같이:

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

따라서 간격에서 일, 시간 등을 추출하고 그에 대응하는 값을 곱하는 것이 유일한 방법인 것 같습니다.

zep의 답변에 따라 고객님의 편의를 위해 다음과 같은 기능으로 정리했습니다.

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 ; 

다음 쿼리를 사용합니다.

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

@Zhaoping Lu의 답변과 비슷하지만 일수에서 초를 얻는 대신 직접 추출합니다.

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

(Postgres에서 작업)SQL 9.6.1)

타임스탬프를 나노초로 변환하는 보다 짧은 방법입니다.

SELECT (EXTRACT(DAY FROM (
    SYSTIMESTAMP --Replace line with desired timestamp --Maximum value: TIMESTAMP '3871-04-29 10:39:59.999999999 UTC'
- TIMESTAMP '1970-01-01 00:00:00 UTC') * 24 * 60) * 60 + EXTRACT(SECOND FROM
    SYSTIMESTAMP --Replace line with desired timestamp
)) *  1000000000 AS NANOS FROM DUAL;

NANOS
1598434427263027000

나노초를 타임스탬프로 변환하는 방법.

SELECT TIMESTAMP '1970-01-01 00:00:00 UTC' + numtodsinterval(
    1598434427263027000 --Replace line with desired nanoseconds
/ 1000000000, 'SECOND') AS TIMESTAMP FROM dual;

TIMESTAMP
26/08/20 09:33:47,263027000 UTC

예상대로 위의 메서드의 결과는 시간대의 영향을 받지 않습니다.

간격을 나노초로 변환하는 더 짧은 방법입니다.

SELECT (EXTRACT(DAY FROM (
    INTERVAL '+18500 09:33:47.263027' DAY(5) TO SECOND --Replace line with desired interval --Maximum value: INTERVAL '+694444 10:39:59.999999999' DAY(6) TO SECOND(9) or up to 3871 year
) * 24 * 60) * 60 + EXTRACT(SECOND FROM (
    INTERVAL '+18500 09:33:47.263027' DAY(5) TO SECOND --Replace line with desired interval
))) * 1000000000 AS NANOS FROM DUAL;

NANOS
1598434427263027000

나노초를 인터벌로 변환하는 방법.

SELECT numtodsinterval(
    1598434427263027000 --Replace line with desired nanoseconds
/ 1000000000, 'SECOND') AS INTERVAL FROM dual;

INTERVAL
+18500 09:33:47.263027

예를 들어 나노초가 아닌 밀리초로 작업하는 경우 10000000을 1000으로 대체합니다.

투고된 메서드 중 몇 가지를 시도했지만 인터벌에 86400을 곱할 때 "ORA-01873: leading precision of the interval is too small"이라는 예외가 발생했기 때문에 자신에게 맞는 메서드를 투고하기로 결정했습니다.

DUAL에서 To_char(ENDTIME, 'yyymmdhh24missff')-to_char(STARTIME, 'yyymmdh24missff') AS DUR를 선택합니다.yyymmdh24miss- SEC YYmmdh24MI DURATION(최소 YYYMDH24MDH24MM)를 지정합니다.

언급URL : https://stackoverflow.com/questions/10092032/extracting-the-total-number-of-seconds-from-an-interval-data-type

반응형