如何在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;