PostgreSQL中的产品聚合

PostgreSQL中的产品聚合,sql,postgresql,aggregate,Sql,Postgresql,Aggregate,我尝试在PostgreSQL中为产品(*)创建聚合。 我行的字段类型为“双精度” 所以,我试着: CREATE AGGREGATE nmul(numeric) ( sfunc = numeric_mul, stype = numeric ); 启动查询时,结果如下: ERROR: function nmul(double precision) does not exist LINE 4: CAST(nmul("cote") AS INT), 谢谢将您的输入从双精度(float8

我尝试在PostgreSQL中为产品(*)创建聚合。 我行的字段类型为“双精度”

所以,我试着:

CREATE AGGREGATE nmul(numeric)
(
   sfunc = numeric_mul,
   stype = numeric
);
启动查询时,结果如下:

ERROR:  function nmul(double precision) does not exist
LINE 4: CAST(nmul("cote") AS INT),

谢谢

将您的输入从
双精度
float8
)转换为
数值
,或者定义聚合的
双精度
风格

你的作品很好:

regress=> CREATE AGGREGATE nmul(numeric)
regress-> (
regress(>    sfunc = numeric_mul,
regress(>    stype = numeric
regress(> );

regress=> SELECT nmul(x) FROM generate_series(1,100) x;
                                                                              nmul                                                                              
----------------------------------------------------------------------------------------------------------------------------------------------------------------
 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
(1 row)
问题在于你的疑问:

regress=> SELECT nmul(x::float8) FROM generate_series(1,100) x;                                                                                                                
ERROR:  function nmul(double precision) does not exist                                                                                                                         
LINE 1: SELECT nmul(x::float8) FROM generate_series(1,100) x;                                                                                                                  
               ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
您可以定义聚合的
float8
版本(
float8
double precision
的同义词):

或者,如果希望保留值的全部精度,请在聚合之前强制转换为
数值,例如:

CAST(nmul(CAST("cote" AS numeric)) AS INT)
或者PostgreSQL特定的速记演员阵容:

nmul("cote"::numeric)::integer
请注意,使用这些产品聚合时,
integer
将很快溢出:

regress=> SELECT nmul(x)::integer FROM generate_series(1,12) x;
   nmul    
-----------
 479001600
(1 row)

regress=> SELECT nmul(x)::integer FROM generate_series(1,13) x;
ERROR:  integer out of range
regress=> 

所以你可能还是想坚持使用
numeric

我从一个非常聪明的人那里找到了一个解决方案,他意识到你可以使用对数来实现这一点():


您可能应该为错误来源的查询显示SQL。数值方法用于计算日志和表达式,每种方法都需要一些相当简单的算术运算的迭代。@ChrisSH当然不需要,但当他想要得到聚合积时,它同样可以用于负数。例如,如果在上述调用中
x<0
,他应将
x
替换为
z=-x
,并将结果乘以
(-1)^x
regress=> SELECT nmul(x)::integer FROM generate_series(1,12) x;
   nmul    
-----------
 479001600
(1 row)

regress=> SELECT nmul(x)::integer FROM generate_series(1,13) x;
ERROR:  integer out of range
regress=> 
select exp(sum(ln(x))) from generate_series(1,5) x;
 exp 
-----
 120
(1 row)