web-dev-qa-db-ja.com

count()を使用してパーセンテージを決定するPostgreSQL(キャストの問題)

次のクエリを実行して、patients列の値を持つrefinstテーブルの行の%を提供しようとしています。私は0の結果を得続けます。

_select (count (refinst) / (select count(*) from patients) * 100) as "Formula" 
from patients;
_

テーブルには15556行あり、select count(refinst) from patientsは、そのうちの1446行がrefinst列に値を持っていることを示しています。クエリから取得したい応答は30.62(_1446/15556*100=30.62XXXXX_、小数点以下第2位に四捨五入)になります。

カウント結果のデータ型(私が想定している整数)と関係があると確信しています。整数を整数で除算し、結果が0未満の場合、0に切り捨てられますか?その場合、カウントの結果を小数点以下2桁の数値としてキャストして、結果も小数点以下2桁に丸める方法を誰かに教えてもらえますか?

このコードを書くには、複数のcountステートメントよりも優れた方法があると思います。特にこのクエリを書くための、よりプロセッサ効率の良い方法を探しています。

20
user3779117
_SELECT (count(refinst) * 100)::numeric / count(*) AS refinst_percentage
FROM   patients;
_
  • 副選択を使用するしない。どちらの集計も同じクエリから派生できます。安い。

  • また、これはウィンドウ関数の場合ではありません。これは、行ごとに1つの結果ではなく、1つの結果を計算するためです。

  • @ a_horseで説明済み のように、小数桁をサポートする任意の 数値型 にキャストします。
    round() を2つの小数桁にしたいのでnumeric(Postgresのdecimalと同じです)。
    しかし、計算に含まれるone値、できれば最初の値をキャストするだけで十分です。 Postgresは情報を失わないタイプを自動的に解決します。

  • 一般に、乗算前に除算することをお勧めします。これは通常、丸め誤差を最小限に抑え、コストを抑えます。
    この場合、最初の乗算(count(refinst) * 100)は、安価で正確なinteger演算で計算できます。 それからnumericにキャストし、次のintegerで除算します(これはではありません追加キャスト)。

2つの小数桁に丸められます。

_SELECT round((count(refinst) * 100)::numeric / count(*), 2) AS refinst_percentage
FROM   patients;
_
26

除算に含まれる各数値を、小数をサポートする型にキャストする必要があります。

select (count(refinst)::decimal / (select count(*) from patients)::decimal) * 100  as "Formula" 
from patients;

また、スカラーサブクエリの代わりにウィンドウ関数を試すこともできます。それはより速いかもしれません:

select (count(refinst)::decimal / (count(*) over ())::decimal) * 100 as "Formula" 
from patients;

このスレッドは数年前のものですが、100ではなく100.0で乗算してみてください。これにより、結果が整数ではなく浮動小数点として自動的にキャストされます。

0
Alan McGill