Product()聚合函数

Mah*_*kar 4 sql oracle statistics

在解释CTE的一些概念时,我们问了一个可爱的问题..我们能找到行的乘法,而我们总是专注于SUM()从一个更新鲜的.这给了我一个想法!只用SQL就可以实现.我也在考虑我们甚至可以支持的最大数量精度,因为产品可能非常庞大.

话虽如此,我们不能编写自己的聚合函数.(我们可以吗?)我在想,只有SQL才有可能.

我想到的2*3就像是给自己增加了2,3倍......但是当这个集合很大时......我不能让它成为可能,因为它可能很麻烦.

Aonther可能性log (a+b) = log a * log b;Anti logarithm,给你的结果.这就是我设法回应的内容.对于Oracle,我会使用一个函数EXECUTE IMMEDIATE.

我们真的可以自我繁衍.这将是更美丽的SQL-ly ..这是纯粹的学习经验.

Gor*_*off 9

logarath/power方法是通常使用的方法.对于Oracle,即:

select exp(sum(ln(col)))
from table;
Run Code Online (Sandbox Code Playgroud)

我不知道为什么原始数据库设计者没有包含PRODUCT()作为聚合函数.我最好的猜测是他们都是计算机科学家,没有统计学家.这些函数在统计学中非常有用,但它们在计算机科学中并不多见.也许他们不想处理溢出问题,这样的函数会暗示(尤其是整数).

顺便说一下,大多数数据库都缺少这个功能,即使那些实现了大量统计聚合功能的数据库也是如此.

编辑:

哦,负数的问题让它变得有点复杂:

select ((case when mod(sum(sign(col)), 2) = 0 then 1 else -1 end) *
        exp(sum(ln(abs(col))))
       ) as product
Run Code Online (Sandbox Code Playgroud)

我不确定在Oracle中处理0s 的安全方法.这是一种"逻辑"方法:

select (case when sum(case when col = 0 then 1 else 0 end) > 0
             then NULL
             when mod(sum(sign(col)), 2) = 0
             then exp(sum(ln(abs(col)))
             else - exp(sum(ln(abs(col)))
        end) 
       ) as product
Run Code Online (Sandbox Code Playgroud)

问题是数据库引擎在执行case语句之前可能会在日志上出错.这恰好是SQL Server的工作原理.我不确定Oracle.

啊,这可能有用:

select (case when sum(case when col = 0 then 1 else 0 end) > 0
             then NULL
             when mod(sum(sign(col)), 2) = 0
             then exp(sum(ln(case when col <> 0 then abs(col) end)))
             else - exp(sum(ln(case when col <> 0 then abs(col) end)))
        end) 
       ) as product
Run Code Online (Sandbox Code Playgroud)

NULL当有一个时它会返回0.

  • @OracleUser...许多数据库(包括Oracle)允许您定义用户定义的聚合函数.所以你总是可以自己定义一个. (3认同)

kro*_*lko 6

在Oracle中,您可以创建自己的聚合函数,
请看一下这个工作示例:http
://sqlfiddle.com/#!4/ee247/1它基于文档中的示例:http:
//docs.oracle. COM/CD/B28359_01/appdev.111/b28425/aggr_functions.htm

create type ProductImpl as object
(
  product NUMBER, 
  static function ODCIAggregateInitialize(sctx IN OUT ProductImpl) return number,
  member function ODCIAggregateIterate(self IN OUT ProductImpl, value IN number) return number,
  member function ODCIAggregateTerminate(self IN ProductImpl, returnValue OUT number, flags IN number) return number,
  member function ODCIAggregateMerge(self IN OUT ProductImpl, ctx2 IN ProductImpl) return number
);
/

create or replace type body ProductImpl is 
static function ODCIAggregateInitialize(sctx IN OUT ProductImpl) 
return number is 
begin
  sctx := ProductImpl(1);
  return ODCIConst.Success;
end;

member function ODCIAggregateIterate(self IN OUT ProductImpl, value IN number) return number is
begin
  self.Product := self.Product * value;
  return ODCIConst.Success;
end;

member function ODCIAggregateTerminate(self IN ProductImpl, 
    returnValue OUT number, flags IN number) return number is
begin
  returnValue := self.Product;
  return ODCIConst.Success;
end;

member function ODCIAggregateMerge(self IN OUT ProductImpl, ctx2 IN ProductImpl) return number is
begin
  self.Product := self.Product * ctx2.Product;
  return ODCIConst.Success;
end;
end;
/

CREATE OR REPLACE FUNCTION Product (input NUMBER) RETURN NUMBER 
PARALLEL_ENABLE AGGREGATE USING ProductImpl;
/
Run Code Online (Sandbox Code Playgroud)


Mah*_*kar 3

Oracle 已经公开了这些ODCI(Oracle Data Cartridge Interface)方法来进行聚合!参考

\n\n
    \n
  • ODCIAggregateDelete() - 从当前组中删除输入值。
  • \n
  • ODCIAggregateInitialize() - 初始化聚合上下文和实现对象类型的实例,并将其作为 OUT 参数返回。
  • \n
  • ODCIAggregateIterate() - 通过处理输入值、更新然后返回聚合上下文来迭代输入行。
  • \n
  • ODCIAggregateMerge() - 在用户定义聚合的串行或并行评估期间将两个聚合上下文合并到单个对象实例中。
  • \n
  • ODCIAggregateTerminate() - 计算聚合计算的结果并执行所有必要的清理,例如释放内存。
  • \n
  • ODCIAggregateWrapContext() 集成当前聚合上下文的所有外部部分以使上下文独立。
  • \n
\n\n

PRODUCT() 聚合函数的代码:

\n\n
CREATE OR REPLACE type PRODUCT_IMPL\nAS\n  object\n  (\n    result NUMBER,\n    static FUNCTION ODCIAggregateInitialize(sctx IN OUT PRODUCT_IMPL)\n    RETURN NUMBER,\n    member FUNCTION ODCIAggregateIterate(self  IN OUT PRODUCT_IMPL,\n                                         value IN NUMBER)\n    RETURN NUMBER,\n    member FUNCTION ODCIAggregateTerminate( self IN PRODUCT_IMPL,\n                                            returnValue OUT NUMBER,\n                                            flags IN NUMBER)\n    RETURN NUMBER,\n    member FUNCTION ODCIAggregateMerge(self IN OUT PRODUCT_IMPL,\n                                       ctx2 IN PRODUCT_IMPL )\n    RETURN NUMBER );\n  /\n  /* 1.Initializes the computation by initializing the aggregation context\xe2\x80\x94the rows over which aggregation is performed: */\nCREATE OR REPLACE type body PRODUCT_IMPL\nIS\n  static FUNCTION ODCIAggregateInitialize(sctx IN OUT PRODUCT_IMPL)\n  RETURN NUMBER\nIS\nBEGIN\n  sctx := PRODUCT_IMPL(1);\n  RETURN ODCIConst.Success;\nEND;\n/* 2.Iteratively processes each successive input value and updates the context: */\nmember FUNCTION ODCIAggregateIterate(self  IN OUT PRODUCT_IMPL,\n                                     value IN NUMBER)\n  RETURN NUMBER\nIS\nBEGIN\n  self.result := value * self.result;\n  RETURN ODCIConst.Success;\nEND;\nmember FUNCTION ODCIAggregateTerminate(\n    self IN PRODUCT_IMPL,\n    returnValue OUT NUMBER,\n    flags IN NUMBER)\n  RETURN NUMBER\nIS\nBEGIN\n  returnValue := self.result;\n  RETURN ODCIConst.Success;\nEND;\nmember FUNCTION ODCIAggregateMerge(self IN OUT PRODUCT_IMPL,\n                                   ctx2 IN PRODUCT_IMPL)\n  RETURN NUMBER\nIS\nBEGIN\n  self.result := self.result;\n  RETURN ODCIConst.Success;\nEND;\nEND;\n/\n\n/* Create A function using the PRODUCT_IMPL implementation we did above */\nCREATE OR REPLACE FUNCTION product(input NUMBER)\nRETURN NUMBER \nPARALLEL_ENABLE AGGREGATE USING PRODUCT_IMPL;\n/\n
Run Code Online (Sandbox Code Playgroud)\n\n

结果:

\n\n
SELECT group_name,product(num) FROM product_test GROUP BY group_name;\n\nMahesh  -60000\nMahesh_1    9\n
Run Code Online (Sandbox Code Playgroud)\n