PostgreSQLで平均を小数点第2位に丸める方法は?


191

Ruby gemの「続編」で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

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


3
エラーメッセージが質問のコードと一致しません。
muが短すぎる

構文エラーはさておき、dba.SEに関するこの密接に関連する質問は、PostgreSQLの倍精度数値の丸めにいくらか光を当てています。
Erwin Brandstetter 2012年

@muistooshort、指摘いただきありがとうございます。「avg」とあるところは「round」と表示されているはずです。編集。
user1626730 2012年

検索結果のために、私はまた、プロンプトからの出力としてこのヒントを得る:HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Vzzarr

回答:


264

PostgreSQLは定義していませんround(double precision, integer)@Mike Sherrill 'Cat Recall'がコメントで説明する理由により、精度を必要とするラウンドのバージョンはでのみ使用できます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の2つの引数の形式を使用するには、丸められる値をキャストする必要がありますround。の::numericように、省略形のキャストに追加するだけround(val::numeric,2)です。


ユーザーへの表示用にフォーマットする場合は、使用しないでください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ますが、先頭のスペースを持つ任意のパディングを望んでいないこと。


うーん。試してみるとROUND(CAST(FLOAT8 '3.1415927' AS NUMERIC),2);「0.314E1」と表示されます。そして、私のコードはROUND(AVG(val),2)まだ記述されていますが、質問で説明したエラーが発生します。
user1626730 2012年

ROUND(CAST(FLOAT8 '3.1415927' AS NUMERIC),2);はPgAdminとRubyで実行しました。PgAdminを使用すると3.14になりますが、Ruby(Sequel gemを使用)を使用すると「0.314E1」になります。これは、なぜ私が...不思議
user1626730

12
「奇妙な理由で、精度を取る丸めのバージョンは数値でのみ使用できます。」浮動小数点数は「便利な近似値」です。浮動小数点数を小数点以下2桁に丸めて別の浮動小数点数を返すようにコードに要求した場合、「正しい」答えに最も近い近似で小数点の右側に2桁しかないという保証はありません。数値は効果的にスケーリングされた整数です。彼らはその問題を抱えていません。
Mike Sherrill 'Cat Recall'

@Catcall良い点-のdoubleバージョンはround返すnumeric必要がある(または(ugh))textので、numeric引数を取ることもできます。
クレイグリンガー

6
@Catcallのコメントを見つけようとしている人のために:これはMike Sherrill 'Cat Recall'
18446744073709551615

88

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

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

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

一部のPostgreSQL関数にはオーバーロード不足していますが、なぜですか(???):「不足している」(!)

PS:丸めに関するもう1つのポイントは精度です。@ IanKenneyの回答を確認してください。


キャスト戦略としてのオーバーロード

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 | ラウンド| 倍精度| 倍精度、テキスト、整数
 myschema | ラウンド| 数値| 倍精度、int
 pg_catalog | ラウンド| 倍精度| 倍精度            
 pg_catalog | ラウンド| 数値| 数値   
 pg_catalog | ラウンド| 数値| 数値、整数          

pg_catalog機能は、デフォルトのものであり参照ビルドで数学関数のマニュアル


38

これで試してください:

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

または単に:

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

5
これは、この質問への私の一日の答えで、はるかに簡潔でまっすぐな前進であることがわかります。:bow:
craastad 2018年

2
こっちも一緒!非常に短くて便利なソリューション。
Alexey Shabramov

7

以下の関数を使用できます

 SELECT TRUNC(14.568,2);

結果が表示されます:

14.56

変数をdesireタイプにキャストすることもできます:

 SELECT TRUNC(YOUR_VAR::numeric,2)

3

ブライアンの応答によると、これを実行してクエリの小数を制限できます。km / hからm / sに変換してダイグラフで表示しますが、ダイグラフで実行すると奇妙に見えました。代わりにクエリで計算を行うとうまく見えます。これはpostgresql 9.5.1にあります。

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


1

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

解決策:addtypeキャストを実行する必要があります。

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


0

ROUND(SUM(amount):: numeric、2)をtotal_amount FROMトランザクションとして選択します

与える:200234.08

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.