38

当减去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 中是否有更优雅的方法?

4

9 回答 9

29

一个简单的方法:

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

想法是将间隔值按 86400 (= 24*60*60) 的倍数转换为天数。然后提取“day”值,这实际上是我们想要的第二个值。

于 2016-08-12T03:32:16.900 回答
26

我希望这会有所帮助:

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> 
于 2012-04-11T06:40:53.853 回答
10

我发现这行得通。显然,如果您使用时间戳进行算术运算,它们将转换为某种内部数据类型,当彼此相减时,将间隔作为数字返回。

简单的?是的。优雅的?不。完成工作了吗?哦耶。

SELECT ( (A + 0) - (B + 0) ) * 24 * 60 * 60 
FROM
(
   SELECT SYSTIMESTAMP A,
          SYSTIMESTAMP - INTERVAL '1' MINUTE B
   FROM DUAL
);
于 2015-01-02T08:06:47.883 回答
4

不幸的是,我认为没有另一种(或更优雅的)方法可以从 pl/sql 中的间隔类型计算总秒数。正如这篇文章提到的:

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

因此,从间隔中提取日期、小时等并将它们与相应的值相乘似乎是唯一的方法。

于 2012-04-10T15:58:28.810 回答
3

基于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 ; 
于 2013-07-03T17:00:57.590 回答
3

使用以下查询:

select (cast(timestamp1 as date)-cast(timestamp2 as date))*24*60*60)
于 2017-09-05T09:15:28.863 回答
1

类似于@Zhaoping Lu 的回答,但直接提取秒数而不是从天数中获取秒数。

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

(在 PostgresSQL 9.6.1 上工作)

于 2019-09-23T12:06:38.813 回答
0

将时间戳转换为纳秒的更短方法。

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

例如,如果您想使用毫秒而不是纳秒,则将 1000000000 替换为 1000。

我尝试了一些发布的方法,但是当将间隔乘以 86400 时出现异常“ORA-01873:间隔的前导精度太小”,所以我决定发布适合我的方法。

于 2020-08-26T11:44:14.963 回答
-2

SELECT to_char(ENDTIME,'yyyymmddhh24missff')-to_char(STARTTIME,'yyyymmddhh24missff') 作为 DUR FROM DUAL; yyyymmddhh24miss- 将以秒为单位给出持续时间 yyyymmddhh24mi 以最小为单位的持续时间 yyyymmddhh24 - 持续时间 - 以天为单位的持续时间

于 2018-06-21T07:59:28.287 回答