自定义oracle聚集函数,类似于功能wm_concat

6 篇文章 0 订阅
Oracle提供了很多预定义好的聚集函数,比如 Max (),  Sum (),  AVG (), 但是这些预定义的聚集函数基本上都是适应于标量数据(scalar data), 对于复杂的数据类型,比如说用户自定义的Object type, Clob等, 是不支持的。 
 
但是,幸运的是, 用户可以通过实现Oracle的Extensibility Framework中的ODCIAggregate interface来创建自定义聚集函数,而且自定义的聚集函数跟内建的聚集函数用法上没有差别。
 
  
 
ODCI是Oracle Data Cartridge Interface 几个单词的首字母缩写, 关于Oracle Data Cartridge,可以参见这里。
 
  
 
  
 
1. Overview  of  User -Defined Aggregate Functions 
 
  
 
通过实现ODCIAggregate rountines来创建自定义的聚集函数。可以通过定义一个对象类型(Object Type),然后在这个类型内部实现ODCIAggregate 接口函数(routines), 可以用任何一种Oracle支持的语言来实现这些接口函数,比如C/C++, JAVA, PL/SQL等。在这个Object Type定义之后,相应的接口函数也都在该Object Type Body内部实现之后, 就可以通过 CREATE  FUNCTION 语句来创建自定义的聚集函数了。
 
  
 
每个自定义的聚集函数需要实现4个ODCIAggregate 接口函数, 这些函数定义了任何一个聚集函数内部需要实现的操作,这些函数分别是 initialization, iteration, merging 和 termination。
 
  
 
(1) ODCIAggregateInitialize 这个函数用来执行初始化操作(initialization). Oracle会调用这个函数来初始化自定义函数计算。 初始化的聚集环境(aggregation context)会以对象实例(object type instance)传回给oracle.
 
  
 
(2) ODCIAggregateIterate 这个函数用来遍历需要处理的数据,被oracle重复调用。每次调用的时候,当前的aggreation context 和 新的(一组)值会作为传入参数。 这个函数会处理这些传入值,然后返回更新后的aggregation context. 这个函数对每一个NON- NULL 的值都会被执行一次。 NULL 值不会被传递个聚集函数。
 
  
 
(3) ODCIAggregateMerge 这个函数用来把两个aggregation context整合在一起,一般用来并行计算中(当一个函数被设置成enable parallel 处理的时候)。
 
  
 
(4) ODCIAggregateTerminate 这个函数是Oracle调用的最后一个函数。它接收aggregation context作为参数,返回最后的aggregate value. 
 
  
 
  
 
Example: 自定义聚集函数是如何工作的
 
SELECT  AVG (T.Sales) FROM  AnnualSales TGROUP  BY  T.State; 
 
为了完成求平均值的计算, AVG 函数经历下面几个步骤:
 
  
 
(1)  Initializes: 初始化Aggregation Context: 
 
         runningSum = 0;  runningCount = 0;
 
  
 
(2) Iteratively 处理每个连续的输入,同时更新aggregation context:
 
       runningSum += inputval;  runningCount ++;
 
  
 
(3) 【这步是可选的】Merge 整合两个aggregation context 返回一个aggregation context. 如果需要这一步的话,它是在termination之前执行。
 
     runningSum   =  runningSum1 + runningSum2;
 
     runningCount  = runningCount1 + runningCount2;
 
  
 
(4)  Terminates 计算出最后的结果, 通过最后的aggregation context来返回最后的aggregated value.
 
     return  (runningSum / runningCount);
 
  
 
如果 AVG 是自定义的聚集函数的话,与之相对应的对象类型(object type)需要实现对应的ODCIAggregate的接口函数。变量runningSum 和 runningCount 是对象类型中的属性(attribute). 
 
  
 
  
 
2. Creating a  User -Defined Aggregate  
 
  
 
创建一个自定义聚集函数分成两步: 如下面两个例子所示:
 
  
 
Example: 如何实现ODCIAggregate接口: 
 
CREATE  TYPE SpatialUnionRoutines(    STATIC  FUNCTION  ODCIAggregateInitialize( ... ) ...,   MEMBER  FUNCTION  ODCIAggregateIterate(...) ... ,   MEMBER  FUNCTION  ODCIAggregateMerge(...) ...,   MEMBER  FUNCTION  ODCIAggregateTerminate(...));  CREATE  TYPE BODY SpatialUnionRoutines  IS  ... END ;  
 
Example:如何定义自定义聚集函数: 
 
CREATE  FUNCTION  SpatialUnion(x Geometry)  RETURN  Geometry AGGREGATE USING SpatialUnionRoutines; 
 
注意在定义函数的时候需要通过Aggregate Using语句来关联上对应的实现了ODCIAggregate接口的Object Type。
 
  
 
  
 
3. Using a  User -Defined Aggregate
 
  
 
自定义的聚集函数可以像内置的聚集函数一样使用, 可以用在 SELECT ORDER  BY HAVING 语句中。下面几个例子说明如何使用上面定义的自定义函数SpatialUnion
 
  
 
Example: 用在 Select 语句中
 
SELECT  SpatialUnion(geometry) FROM  countiesGROUP  BY  state 
 
  
 
Example: 用在 Having 语句中,
 
SELECT  groupcol, MyUDAG(col) FROM  tabGROUP  BY  groupcolHAVING MyUDAG(col) > 100ORDER  BY  MyUDAG(col); 
 
Example: 其他
 
SELECT  ..., MyUDAG(col) FROM  tabGROUP  BY  ROLLUP (gcol1, gcol2) 
 
自定义聚集函数可以跟 All Distinct 一起使用, 亦可以用在 Group  by 的扩展语句中,像 ROLLUP CUBE grouping  sets. 
 
  
 
  
 
4. Evaluating  User -Defined Aggregates  in  Parallel 
 
  
 
跟内置的聚集函数一样,自定义的聚集函数也可以并行来处理, 
  
 
 
 
  
 
需要注意的是, 自定义的聚集函数需要声明为parallel-enabled, 如下
 
CREATE  FUNCTION  MyUDAG(...)  RETURN  ...PARALLEL_ENABLE AGGREGATE USING MyAggrRoutines; 
 
  
 
5.  User -Defined Aggregates  and  Analytic Functions
 
自定义的聚集函数可以被当做Analytic函数来用, 
 
  
 
SELECT  Account_number, Trans_date, Trans_amount,   MyAVG (Trans_amount) OVER      PARTITION  BY  Account_number  ORDER  BY  Trans_date      RANGE INTERVAL  '7'  DAY  PRECEDING)  AS  mavg_7dayFROM Ledger; 
 
6.  Reusing the Aggregation Context  for  Analytic Functions 
 
当一个自定义的聚集函数被用来做Analytic  Function 的时候,对每条记录对应的window都会计算一次aggregate。 一般的说来,每个连续的窗口包含大部分相同的数据集合。 
 
可以通过实现ODCIAggregateDelete接口函数来让Oracle更有效地复用aggregation context. 
 
  
 
7. An complete example  for  Creating  and  Using a  User -Defined Aggregate  Function
 
SecondMax()返回一组数里面第二大的那个值。
 
(1) 实现类型SecondMaxImpl,该类型包含了ODCIAggregate接口函数, 
 
create  type SecondMaxImpl  as  object(   max  NUMBER,  -- highest value seen so far   secmax NUMBER, -- second highest value seen so far  static function ODCIAggregateInitialize(sctx IN OUT SecondMaxImpl)     return number,  member function ODCIAggregateIterate(self IN OUT SecondMaxImpl,     value IN number) return number,  member function ODCIAggregateTerminate(self IN SecondMaxImpl,     returnValue OUT number, flags IN number) return number,  member function ODCIAggregateMerge(self IN OUT SecondMaxImpl,     ctx2 IN SecondMaxImpl) return number);/ 
 
  
 
(2).  实现类型SecondMaxImpl的body, 
 
create  or  replace  type body SecondMaxImpl  is  static  function  ODCIAggregateInitialize(sctx  IN  OUT  SecondMaxImpl)  return  number  is  begin   sctx := SecondMaxImpl(0, 0);   return  ODCIConst.Success; end ; member  function  ODCIAggregateIterate(self  IN  OUT  SecondMaxImpl, value  IN  number)  return  number isbegin  if value > self. max  then     self.secmax := self. max ;    self. max  := value;  elsif value > self.secmax  then     self.secmax := value;   end  if;   return  ODCIConst.Success; end ; member  function  ODCIAggregateTerminate(self  IN  SecondMaxImpl,     returnValue  OUT  number, flags  IN  number)  return  number isbegin  returnValue := self.secmax;   return  ODCIConst.Success; end ; member  function  ODCIAggregateMerge(self  IN  OUT  SecondMaxImpl, ctx2  IN  SecondMaxImpl)  return  number isbegin  if ctx2. max  > self. max  then     if ctx2.secmax > self.secmax  then        self.secmax := ctx2.secmax;     else       self.secmax := self. max ;     end  if;    self. max  := ctx2. max ;  elsif ctx2. max  > self.secmax  then     self.secmax := ctx2. max ;   end  if;   return  ODCIConst.Success; end ; end ;/ 
 
 
 
 
 
 
 
 
 
 
 
 
  
 
(3). 创建自定义聚集函数SecondMax()
 
CREATE  FUNCTION  SecondMax (input NUMBER)  RETURN  NUMBER PARALLEL_ENABLE AGGREGATE USING SecondMaxImpl; 
 
(4). 使用自定义聚集函数SecondMax()
 
  
 
SELECT  SecondMax(salary), department_idFROM employeesGROUP  BY  department_idHAVING SecondMax(salary) > 9000;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值