Thực hiện các khoảng thời gian, và đặc biệt là thực hiện tổng hợp (tổng, trung bình) trên nhiều khoảng thời gian hoặc nhóm khoảng thời gian không hề đơn giản trong Oracle. Chức năng AVG không hoạt động trên khoảng thời gian dấu thời gian, nó mong đợi các con số. Vì vậy, chúng ta sẽ cần tạo đối tượng và hàm tổng hợp của riêng mình để thực hiện việc này.
Đầu tiên, đặc điểm đối tượng :
CREATE OR REPLACE TYPE AvgInterval
AS OBJECT (
runningSum INTERVAL DAY(9) TO SECOND(9),
runningCnt number,
STATIC FUNCTION ODCIAggregateInitialize
( actx IN OUT AvgInterval
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateIterate
( self IN OUT AvgInterval,
val IN DSINTERVAL_UNCONSTRAINED
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateTerminate
( self IN AvgInterval,
returnValue OUT DSINTERVAL_UNCONSTRAINED,
flags IN NUMBER
) RETURN NUMBER,
MEMBER FUNCTION ODCIAggregateMerge
(self IN OUT AvgInterval,
ctx2 IN AvgInterval
) RETURN NUMBER
);
Và nội dung đối tượng :
CREATE OR REPLACE TYPE BODY AvgInterval AS
STATIC FUNCTION ODCIAggregateInitialize
( actx IN OUT AvgInterval
) RETURN NUMBER IS
BEGIN
IF actx IS NULL THEN
actx := AvgInterval (INTERVAL '0 0:0:0.0' DAY TO SECOND, 0);
ELSE
actx.runningSum := INTERVAL '0 0:0:0.0' DAY TO SECOND;
actx.runningCnt := 0;
END IF;
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateIterate
( self IN OUT AvgInterval,
val IN DSINTERVAL_UNCONSTRAINED
) RETURN NUMBER IS
BEGIN
self.runningSum := self.runningSum + val;
self.runningCnt := self.runningCnt + 1;
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateTerminate
( self IN AvgInterval,
ReturnValue OUT DSINTERVAL_UNCONSTRAINED,
flags IN NUMBER
) RETURN NUMBER IS
BEGIN
if (runningCnt <> 0) then
returnValue := (self.runningSum/runningCnt);
else
returnValue := self.runningSum;
end if;
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateMerge
(self IN OUT AvgInterval,
ctx2 IN AvgInterval
) RETURN NUMBER IS
BEGIN
self.runningSum := self.runningSum + ctx2.runningSum;
self.runningCnt := self.runningCnt + ctx2.runningCnt;
RETURN ODCIConst.Success;
END;
END;
Cuối cùng, chức năng sử dụng đối tượng trên :
CREATE OR REPLACE FUNCTION avg_interval( x DSINTERVAL_UNCONSTRAINED)
RETURN DSINTERVAL_UNCONSTRAINED PARALLEL_ENABLE
AGGREGATE USING AvgInterval;
Bây giờ, chúng tôi có thể sử dụng nó như thế này :
with x as (
select systimestamp - 1/24 as created_date, systimestamp as modified_date from dual
union
select systimestamp - 2/24 as created_date, systimestamp as modified_date from dual
union
select systimestamp - 3/24 as created_date, systimestamp as modified_date from dual
)
select avg_interval(modified_date - created_date)
from x;
Đầu ra:
+00 02:00:00.562669
Chúng tôi cũng có thể tổng hợp qua các nhóm với cái này :
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, avg_interval(duration)
from x
group by state;
Đầu ra:
FL +00 01:32:35.000000
GA +00 01:01:00.000000