Общая сумма временных меток

#oracle #sum #timestamp #ora-00932

#Oracle #сумма #временная метка #ora-00932

Вопрос:

У меня есть следующий запрос для вычисления метки времени суммирования

 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: несогласованные типы данных: ожидаемое ЧИСЛО получено С ИНТЕРВАЛОМ ОТ ДНЯ До СЕКУНДЫ.

Поймите, что для этого требуется что-то вроде этого

 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;
  

Как можно достичь вместе с подзапросами, которые извлекают данные из столбцов типа временной метки?

Ответ №1:

Вы не можете суммировать INTERVAL DAY TO SECOND в Oracle. Я думаю, что это один из самых популярных запросов на открытие функций.

Вы можете преобразовать 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'
);
  

Комментарии:

1. это здорово 🙂 ПРИВЕДЕНИЕ к ДАТЕ отлично работает вместе с 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. Используйте функцию извлечения, чтобы получить секунды из time_spent.

Комментарии:

1. Это работает, только если разница составляет менее минуты.

2. да, я выполнил вычисления вручную, они не точны по сравнению с решением @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
/
  

Комментарии:

1. @wernfried Прочитайте мой пример более внимательно: я показал, как суммировать интервалы

2. @WernfriedDomscheit мой ответ показывает, как это сделать… Что вы пытались сказать в своих комментариях?