sql >> データベース >  >> RDS >> PostgreSQL

同じSELECTsqlクエリでSUM()からパーセントを計算する

    この質問には、見た目以上のものがあります。

    シンプルバージョン

    これは大いに より速く、より簡単に:

    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では引用符で囲まれていない大文字と小文字が混在する識別子を使用しないでください。私はこの愚かさから来る絶望的な質問が多すぎるのを見てきました。私が何について話しているのか疑問に思われる場合は、マニュアルの「識別子とキーワード」の章をお読みください。



    1. データベース内のすべてのテーブルのドロップテーブルステートメントを生成する方法-SQLServer/T-SQLチュートリアルパート48

    2. MySQL8共通テーブル式CTE

    3. T-SQLで日付をフォーマットする方法

    4. MySQLで小文字を大文字に変換する方法