5

我有一个表,其中有一列名为duration. 它的数据类型是VARCHAR2.

我想对列求和duration

00:56:30
02:08:40
01:01:00

总计=>04:05:10

如何使用 ANSI SQL 或 Oracle SQL 做到这一点?

4

4 回答 4

10

您可以使用 分隔小时、分钟和秒SUBSTR,然后SUM向上,最后使用NUMTODSINTERVAL函数将其转换为INTERVAL类型。

SELECT NUMTODSINTERVAL (SUM (total_secs), 'second')
  FROM (SELECT   SUBSTR (duration, 1, 2) * 3600
               + SUBSTR (duration, 4, 2) * 60
               + SUBSTR (duration, 7, 2) total_secs
          FROM user_tab);
于 2013-05-29T12:04:59.453 回答
7

我认为最好将您的字符串转换为INTERVAL第一个,并将这些值添加为日期值。类似于以下内容:

select   to_dsinterval('0 00:56:30') 
       + to_dsinterval('0 02:08:40') 
       + to_dsinterval('0 01:01:00') myinterval from dual;

MYINTERVAL
-------------------
+000000000 04:06:10
于 2013-05-29T11:36:52.383 回答
4

甲骨文

select 
numtodsinterval(sum(
  to_char(to_date(duration, 'HH24:MI:SS'), 'HH24') * 3600 + 
  to_char(to_date(duration, 'HH24:MI:SS'), 'MI') * 60+
  to_char(to_date(duration, 'HH24:MI:SS'), 'SS')
  ), 'second'
) as SUMTOTAL
from tbl;

第二次查询

select 
numtodsinterval(hr+mn+sc, 'second')
from 
(
select 
sum(to_char(to_date(duration, 'HH24:MI:SS'), 'HH24') * 3600) as hr,
sum(to_char(to_date(duration, 'HH24:MI:SS'), 'MI') * 60) as mn,
sum(to_char(to_date(duration, 'HH24:MI:SS'), 'SS'))as sc
from tbl) tmp

小提琴

在 SQL FIDDLE 中返回对象的示例。在你的机器上试试

为 MYSQL

试试这个

select sec_to_time(sum(time_to_sec(duration))) from tbl

小提琴

| SEC_TO_TIME(SUM(TIME_TO_SEC(DURATION))) |
-------------------------------------------
|          January, 01 1970 04:06:10+0000 |
于 2013-05-29T11:42:16.967 回答
2

为了好玩,我编写了自己的聚合函数,可以对区间求和(参见@Yasir 的帖子)。这可以修改为在内部进行 varchar 到间隔转换,但我现在会尽可能简单)。

首先创建对象类型规范:

CREATE OR REPLACE TYPE SumInterval 
AS OBJECT (

runningSum INTERVAL DAY(9) TO SECOND(9),

STATIC FUNCTION ODCIAggregateInitialize
  ( actx IN OUT SumInterval
  ) RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateIterate
  ( self  IN OUT SumInterval,
    val   IN       DSINTERVAL_UNCONSTRAINED
  ) RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateTerminate
  ( self             IN   SumInterval,
    returnValue  OUT DSINTERVAL_UNCONSTRAINED,
    flags           IN   NUMBER
  ) RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateMerge
  (self  IN OUT SumInterval,
   ctx2 IN      SumInterval
  ) RETURN NUMBER

);

和对象主体:

CREATE OR REPLACE TYPE BODY SumInterval AS

STATIC FUNCTION ODCIAggregateInitialize
  ( actx IN OUT SumInterval
  ) RETURN NUMBER IS 
  BEGIN
    IF actx IS NULL THEN
      actx := SumInterval (INTERVAL '0 0:0:0.0' DAY TO SECOND);
    ELSE
      actx.runningSum := INTERVAL '0 0:0:0.0' DAY TO SECOND;
    END IF;
    RETURN ODCIConst.Success;
  END;

MEMBER FUNCTION ODCIAggregateIterate
  ( self  IN OUT SumInterval,
    val   IN     DSINTERVAL_UNCONSTRAINED
  ) RETURN NUMBER IS
  BEGIN
    self.runningSum := self.runningSum + val;
    RETURN ODCIConst.Success;
  END;

MEMBER FUNCTION ODCIAggregateTerminate
  ( self        IN  SumInterval,
    ReturnValue OUT DSINTERVAL_UNCONSTRAINED,
    flags       IN  NUMBER
  ) RETURN NUMBER IS
  BEGIN
    returnValue := self.runningSum;
    RETURN ODCIConst.Success;
  END;

MEMBER FUNCTION ODCIAggregateMerge
  (self IN OUT SumInterval,
   ctx2 IN     SumInterval
  ) RETURN NUMBER IS
  BEGIN
    self.runningSum := self.runningSum + ctx2.runningSum;
    RETURN ODCIConst.Success;
  END;

END;

最后是使用此对象类型的函数:

CREATE OR REPLACE FUNCTION sum_interval( x DSINTERVAL_UNCONSTRAINED) 
RETURN DSINTERVAL_UNCONSTRAINED  PARALLEL_ENABLE
AGGREGATE USING SumInterval;

现在您可以使用新的“sum_interval”,如下所示:

with x as (
select to_dsinterval('0 00:56:30') as duration from dual
union
select to_dsinterval('0 02:08:40') as duration from dual
union
select to_dsinterval('0 01:01:00') as duration from dual
)
select sum_interval(duration)
from x;

输出:

SUM_INTERVAL(DURATION)
+00 04:06:10.000000

这样做的另一个好处是它可以像典型的聚合函数一样使用。例如,我们可以将其用作组函数:

with x as (
select 'FL' as state, to_dsinterval('0 00:56:30') as duration from dual
union
select 'FL' as state, to_dsinterval('0 02:08:40') as duration from dual
union
select 'GA' as state, to_dsinterval('0 01:01:00') as duration from dual
)
select state, sum_interval(duration)
from x
group by state;

输出:

STATE   SUM_INTERVAL(DURATION)
FL  +00 03:05:10.000000
GA  +00 01:01:00.000000
于 2013-05-29T14:22:53.180 回答