4

我尝试在 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),

谢谢

4

2 回答 2

10

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

select exp(sum(ln(x))) from generate_series(1,5) x;
 exp 
-----
 120
(1 row)
于 2017-08-23T14:36:24.230 回答
8

将您的输入从double precision( float8) 转换为numeric,或定义double precision聚合的风格。

您的聚合工作正常:

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):

regress=> CREATE AGGREGATE nmul(double precision)
(
   sfunc = float8mul,
   stype = float8
);

regress=> SELECT nmul(x::float8) FROM generate_series(1,100) x;
         fmul          
-----------------------
 9.33262154439441e+157
(1 row)

numeric如果要保留值的完整精度,或者在聚合之前强制转换,例如:

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

于 2012-10-31T10:48:42.950 回答