【问题标题】:Sum totals of timestamp时间戳总和
【发布时间】:2020-12-14 00:53:50
【问题描述】:

我有以下查询来计算总和时间戳

SELECT SUM(TIME_SPENT) FROM
(
 select a - b as time_spent from tbl1 where name = 'xxx'
 union all
select c - d as time_spent from tbl2 where name= 'yyy'
)a;

子查询返回结果为 +00 00:01:54.252000 但是整个查询返回错误为 ORA-00932:不一致的数据类型:预期的 NUMBER 得到了 INTERVAL DAY TO SECOND。

理解它需要这样的东西

SELECT COALESCE (
(to_timestamp('2014-09-22 16:00:00','yyyy/mm/dd HH24:MI:SS') - to_timestamp('2014-09-22 09:00:00','yyyy/mm/dd HH24:MI:SS')) -
(to_timestamp('2014-09-22 16:00:00','yyyy/mm/dd HH24:MI:SS') - to_timestamp('2014-09-22 09:00:00','yyyy/mm/dd HH24:MI:SS')), INTERVAL '0' DAY) FROM DUAL;

如何实现与子查询一起从 Timestamp 类型的列中检索数据?

【问题讨论】:

    标签: oracle sum timestamp ora-00932


    【解决方案1】:

    您不能在 Oracle 中对 INTERVAL DAY TO SECOND 求和。我认为这是评价最高的开放功能请求之一。

    您可以将TIMESTAMP 转换为DATE 值,那么结果就是天数的差异。乘以24*60*60 是不是更喜欢秒数:

    SELECT SUM(TIME_SPENT) * 24*60*60 FROM FROM
    (
     select CAST(a AS DATE) - CAST(b AS DATE) as time_spent from tbl1 where name = 'xxx'
     union all
    select CAST(d AS DATE) - CAST(d AS DATE) as time_spent from tbl2 where name= 'yyy'
    );
    

    或者您可以编写一个将INTERVAL DAY TO SECOND 转换为秒的函数:

    CREATE OR REPLACE FUNCTION GetSeconds(ds INTERVAL DAY TO SECOND) DETERMINISTIC RETURN NUMBER AS
    BEGIN
        RETURN EXTRACT(DAY FROM ds)*24*60*60 
            + EXTRACT(HOUR FROM ds)*60*60 
            + EXTRACT(MINUTE FROM ds)*60 
            + EXTRACT(SECOND FROM ds);
    END;
    

    并像这样使用它:

    SELECT SUM(TIME_SPENT), numtodsinterval(SUM(TIME_SPENT), 'second')
    (
     select GetSeconds(a-b) as time_spent from tbl1 where name = 'xxx'
     union all
    select GetSeconds(c-d) as time_spent from tbl2 where name= 'yyy'
    );
    

    【讨论】:

    • 太好了 :) CAST into DATE 与 sum () * 24*60*60 完美配合
    【解决方案2】:

    尝试使用以下查询

     SELECT sum(extract(second from time_spent)) FROM
     (
      select a - b as time_spent from test2 where name = 'xxx'
      union all
      select c - d as time_spent from tbl2 where name= 'yyy'
     )a;
    

    看起来 time_spent 列是表中的时间戳类型,并且它无法在 Sum 函数中传递正确的数据类型。使用 extract 函数从 time_spent 中获取 Seconds。

    【讨论】:

    • 这仅在差异小于一分钟时有效。
    • 是的,我进行了手动计算,与@WernfriedDomscheit 的解决方案相比并不准确
    【解决方案3】:
    with t(a,b) as (
      select timestamp'2014-09-22 16:00:00.000', timestamp'2014-09-23 16:00:00.001' from dual union all
      select timestamp'2014-09-22 16:00:00.000', timestamp'2014-09-24 16:00:00.001' from dual union all
      select timestamp'2014-09-22 16:00:00.000', timestamp'2014-09-25 16:00:00.001' from dual union all
      select timestamp'2014-09-22 16:00:00.000', timestamp'2014-09-26 16:00:00.001' from dual union all
      select timestamp'2014-09-22 16:00:00.000', timestamp'2014-09-27 16:00:00.001' from dual
    )
    select
                            sum( (date'1-1-1'+(b-a)*24*60*60 - date'1-1-1'))     as ssum_seconds_1,
                      round(sum( (date'1-1-1'+(b-a)*24*60*60 - date'1-1-1')), 3) as ssum_seconds_rounded,
     numtodsinterval( round(sum( (date'1-1-1'+(b-a)*24*60*60 - date'1-1-1')), 3), 'second') dsint
    from t
    /
    

    【讨论】:

    • @wernfried 仔细阅读我的例子:我展示了如何对区间求和
    • @WernfriedDomscheit 我的回答展示了如何做到这一点......你在你的 cmets 中试图说什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多