如何在PostgreSQL中将平均值舍入到小数点后两位?

我通过Ruby gem'sequel'使用PostgreSQL。

我正在尝试四舍五入到小数点后两位。

这是我的代码:

SELECT ROUND(AVG(some_column),2) FROM table 

我得到以下错误:

 PG::Error: ERROR: function round(double precision, integer) does not exist (Sequel::DatabaseError) 

当我运行下面的代码时,我得到没有错误:

 SELECT ROUND(AVG(some_column)) FROM table 

有谁知道我在做什么错?

PostgreSQL没有定义round(double precision, integer) 。 由于@Catcall在注释中解释的原因,需要精确度的回合的版本只能用于numeric

 regress=> SELECT round( float8 '3.1415927', 2 ); ERROR: function round(double precision, integer) does not exist regress=> \df *round* List of functions Schema | Name | Result data type | Argument data types | Type ------------+--------+------------------+---------------------+-------- pg_catalog | dround | double precision | double precision | normal pg_catalog | round | double precision | double precision | normal pg_catalog | round | numeric | numeric | normal pg_catalog | round | numeric | numeric, integer | normal (4 rows) regress=> SELECT round( CAST(float8 '3.1415927' as numeric), 2); round ------- 3.14 (1 row) 

(在上面,注意float8只是double precision的简写别名,你可以看到PostgreSQL正在把它扩展到输出中)。

您必须将值舍入为numeric以使用round的双参数forms。 只需追加::numeric为速记cast,如round(val::numeric,2)


如果您要格式化显示给用户,请不要使用round 。 使用to_char (请参阅手册中的数据types格式化函数 ),它可以让您指定一种格式,并为您提供text结果,而不会受到客户端语言对numeric值可能造成的任何问题的影响。 例如:

 regress=> SELECT to_char(float8 '3.1415927', 'FM999999999.00'); to_char --------------- 3.14 (1 row) 

to_char将为您to_char数字作为格式化的一部分。 FM前缀告诉to_char你不想用前导空格进行任何填充。

尝试一下铸造的旧语法,

 SELECT ROUND(AVG(some_column)::numeric,2) FROM table; 

适用于任何版本的PostgreSQL。

在某些PostgreSQL函数中缺less重载 ,为什么(???):我认为“这是一个缺乏”(!),但是@CraigRinger,@Catcall和PostgreSQL团队对于“pg的历史基本原理”是一致的。

PS:关于四舍五入的另一点是准确性 ,请检查@ IanKenney的答案 。


超载作为铸造战略

你可以重载 ROUND函数,

  CREATE FUNCTION ROUND(float,int) RETURNS NUMERIC AS $$ SELECT ROUND($1::numeric,$2); $$ language SQL IMMUTABLE; 

现在你的指令会正常工作,尝试(函数创build后)

  SELECT round(1/3.,4); -- 0.3333 numeric 

但是它返回一个NUMERICtypes…为了保留第一个通用使用重载,当提供一个TEXT参数时,我们可以返回一个FLOATtypes,

  CREATE FUNCTION ROUND(float, text, int DEFAULT 0) RETURNS FLOAT AS $$ SELECT CASE WHEN $2='dec' THEN ROUND($1::numeric,$3)::float -- ... WHEN $2='hex' THEN ... WHEN $2='bin' THEN... complete! ELSE 'NaN'::float -- like an error message END; $$ language SQL IMMUTABLE; 

尝试

  SELECT round(1/3.,'dec',4); -- 0.3333 float! SELECT round(2.8+1/3.,'dec',1); -- 3.1 float! SELECT round(2.8+1/3.,'dec'::text); -- need to cast string? pg bug 

PS:重载后检查\df round ,会显示类似的东西,

 架构| 名称| 结果数据types| 参数数据types 
 ------------ + ------- + ------------------ + ---------- ------------------
  myschema | 圆| 双精度| 双精度,文本,整数
  myschema | 圆| 数字| 双精度,整数
  pg_catalog | 圆| 双精度| 双精度            
  pg_catalog | 圆| 数字| 数字   
  pg_catalog | 圆| 数字| 数字,整数          

pg_catalog函数是默认函数,请参阅内置math函数的手册 。

试试这个:

 SELECT to_char (2/3::float, 'FM999999990.00'); -- RESULT: 0.67 

或者干脆:

 SELECT round (2/3::DECIMAL, 2)::TEXT -- RESULT: 0.67 

错误:函数round(double precision,integer)不存在

解决scheme :您需要添加types转换然后它将工作

例如: round(extract(second from job_end_time_t)::integer,0)

根据Bryan的回答,你可以这样做来限制查询中的小数。 我从公里/小时转换到米/秒,并显示在dygraphs,但是当我在dygraphs做它看起来很奇怪。 在查询中进行计算时看起来很好。 这是在postgresql 9.5.1上。

 select date,(wind_speed/3.6)::numeric(7,1) from readings; 
Interesting Posts