web-dev-qa-db-ja.com

PostgreSQLで平均を小数点以下2桁に丸める方法は?

私はRuby gem 'sequel'を通してPostgreSQLを使っています。

小数点以下2桁に丸めようとしています。

これが私のコードです:

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

誰かが私が間違っていることを知っていますか?

140
user1626730

PostgreSQLはround(double precision, integer)を定義していません。 @Catcallがコメントで説明している理由で、精度を取るroundのバージョンは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)

(上記では、float8double precisionの単なる省略形のエイリアスです。PostgreSQLが出力でそれを拡張していることがわかります)。

2引数形式のnumericを使用するには、値をroundに丸めるようにキャストする必要があります。 round(val::numeric,2)のように、省略形のキャストには::numericを追加するだけです。


ユーザーへの表示用にフォーマットしている場合は、roundを使用しないでください。 to_char(マニュアルの データ型フォーマット関数 を参照)を使用すると、フォーマットを指定でき、クライアント言語がtextの値を使用した場合の影響を受けないnumericの結果が得られます。例えば:

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

to_charはフォーマットの一部としてあなたのために数字を丸めます。 FMという接頭辞は、先頭のスペースを埋め込む必要がないことをto_charに伝えます。

197
Craig Ringer

キャストのための古い構文も試してください。

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

postgreSQLのどのバージョンでも動作します。

いくつかのPostgreSQL関数にはオーバーロードの欠如があります、なぜ(???):私は「それは欠如である」と思います(!)、しかし@ CraigRinger、@ Catcall、そしてPostgreSQLチームは "pgの歴史的根拠"について同意します。

シモンズ:四捨五入についてのもう一つのポイントは精度、チェック @ IanKenney's answer です。


キャスティング戦略としての過負荷

オーバーロード ROUND関数で、

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

これであなたの命令はうまくいくでしょう、試してみてください(関数作成後)

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

しかし、それはNUMERIC型を返します...最初のcommom-usageオーバーロードを保持するために、TEXTパラメータが提供されたときにFLOAT型を返すことができます。

 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をチェックすると、

スキーマ|名前|結果データ型引数のデータ型
 ------------ + ------- + ------------------ +  - -------------------------- 
 myschema |ラウンド|倍精度|倍精度、テキスト、整数
ラウンド|数値|倍精度、整数
 pg_catalog |ラウンド|倍精度|倍精度
 pg_catalog |ラウンド|数値|数値
 pg_catalog |ラウンド|数値|数値、整数

pg_catalog関数はデフォルトのものです。 組み込み数学関数のマニュアル を参照してください。

64
Peter Krauss

これを試してみてください。

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

または単に:

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

Bryan's レスポンスによると、これを実行してクエリ内の小数部を制限することができます。 km/hからm/sに変換してグラフに表示しましたが、グラフにしたときは奇妙に見えました。代わりにクエリで計算をするときは、きれいに見えます。これはpostgresql 9.5.1にあります。

select date,(wind_speed/3.6)::numeric(7,1) from readings;
2
kometen

エラー:関数round(倍精度、整数)が存在しません

Solution:型キャストを追加する必要があります。それでうまくいくでしょう

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

1
user5702982

あなたは以下の機能を使用することができます

 SELECT TRUNC(14.568,2);

結果は次のようになります。

14.56

変数を希望の型にキャストすることもできます。

 SELECT TRUNC(YOUR_VAR::numeric,2)
0
info vif