この質問には、見た目以上のものがあります。
シンプルバージョン
これは大いに より速く、より簡単に:
SELECT property_name
,(count(value_a = value_b OR NULL) * 100) / count(*) AS pct
FROM my_obj
GROUP BY 1;
結果:
property_name | pct
--------------+----
prop_1 | 17
prop_2 | 43
どうやって?
-
このための関数はまったく必要ありません。
-
value_b
を数える代わりに (最初から始める必要はありません)合計を計算するには、count(*)
を使用します 合計で。より速く、よりシンプルに。 -
これは、
NULL
がないことを前提としています 値。つまり両方の列が定義されていますNOT NULL
。質問に情報がありません。
そうでない場合、元のクエリはおそらくあなたが思っていることをしていないです。 。いずれかの値がNULLの場合、バージョンはその行をまったくカウントしません。 ゼロ除算を誘発することもできます この方法では例外です。
このバージョンはNULLでも機能します。count(*)
値に関係なく、すべての行のカウントを生成します。 -
カウントの仕組みは次のとおりです。
TRUE OR NULL = TRUE FALSE OR NULL = NULL
count()
NULL値を無視します。 Voilá。 -
演算子の優先順位は、
=
を支配しますOR
の前にバインドします 。かっこを追加してわかりやすくすることができます:count ((value_a = value_b) OR FALSE)
-
count NULLIF(<expression>, FALSE)
-
count()
の結果タイプbigint
です デフォルト。
分割bigint / bigint
、小数桁を切り捨てる 。
小数桁を含める
100.0
を使用する (小数桁付き)計算をnumeric
に強制します これにより、小数桁を保持します。
round()
を使用することをお勧めします これで:
SELECT property_name
,round((count(value_a = value_b OR NULL) * 100.0) / count(*), 2) AS pct
FROM my_obj
GROUP BY 1;
結果:
property_name | pct
--------------+-------
prop_1 | 17.23
prop_2 | 43.09
余談ですが:
私はvalue_a
を使用しています valueA
の代わりに 。 PostgreSQLでは引用符で囲まれていない大文字と小文字が混在する識別子を使用しないでください。私はこの愚かさから来る絶望的な質問が多すぎるのを見てきました。私が何について話しているのか疑問に思われる場合は、マニュアルの「識別子とキーワード」の章をお読みください。