不幸的是,Oracle 不支持大多数带间隔的函数。有许多解决方法,但它们都有一些缺点(值得注意的是,没有一个是符合 ANSI-SQL 的)。
最好的答案(正如@justsalt 后来发现的那样)是编写一个自定义函数来将间隔转换为数字,平均数字,然后(可选)转换回间隔。Oracle 12.1 及更高版本支持使用WITH块声明函数来执行此操作:
with
    function fn_interval_to_sec(i in dsinterval_unconstrained)
        return number is
    begin
        return ((extract(day from i) * 24
               + extract(hour from i) )*60
               + extract(minute from i) )*60
               + extract(second from i);
    end;
select numtodsinterval(avg(fn_interval_to_sec(endtime-starttime)), 'SECOND') 
  from timings;
如果您使用的是 11.2 或更早版本,或者您不想在 SQL 语句中包含函数,则可以将其声明为存储函数:
create or replace function fn_interval_to_sec(i in dsinterval_unconstrained)
    return number is
begin
    return ((extract(day from i) * 24
           + extract(hour from i) )*60
           + extract(minute from i) )*60
           + extract(second from i);
end;
然后,您可以按预期在 SQL 中使用它:
select numtodsinterval(avg(fn_interval_to_sec(endtime-starttime)), 'SECOND') 
  from timings;
使用dsinterval_unconstrained
为函数参数使用 PL/SQL 类型别名dsinterval_unconstrained可确保您拥有最大的精度/规模;INTERVAL DAY TO SECOND默认DAY精度为 2 位(意味着 ±100 天或超过 100 天的任何内容都是溢出并引发异常)并SECOND缩放为 6 位。
此外,如果您尝试在参数中指定任何精度/比例,Oracle 12.1 将引发 PL/SQL 错误:
with
    function fn_interval_to_sec(i in interval day(9) to second(9))
        return number is
        ...
ORA-06553: PLS-103: Encountered the symbol "(" when expecting one of the following: to
备择方案
自定义聚合函数
Oracle 支持用 PL/SQL 编写的自定义聚合函数,这将允许您对语句进行最小的更改:
select ds_avg(endtime-starttime) from timings;
但是,这种方法有几个主要缺点:
- 您必须在数据库中创建PL/SQL 聚合对象,这可能是不希望或不允许的;
 
- 您无法命名它
avg,因为 Oracle 将始终使用内置avg函数而不是您自己的。(从技术上讲你可以,但是你必须用模式来限定它,这违背了目的。) 
- 正如@vadzim 所指出的,聚合 PL/SQL 函数具有显着的性能开销。
 
日期算术
如果您的价值观相距不远,@vadzim 的方法也适用:
select avg((sysdate + (endtime-starttime)*24*60*60*1000000 - sysdate)/1000000.0) 
  from timings;
但请注意,如果间隔太大,(endtime-starttime)*24*60*60*1000000表达式将溢出并抛出ORA-01873: the leading precision of the interval is too small。在这个精度(1μs)下,差异不能大于或等于00:16:40幅度,因此对于小间隔是安全的,但不是全部。
最后,如果您愿意失去所有亚秒级精度,您可以将TIMESTAMP列转换为DATE; DATE从 a 中减去 aDATE将返回具有第二精度的天数(归功于@jimmyorr):
select avg(cast(endtime as date)-cast(starttime as date))*24*60*60 
  from timings;