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

PostgreSQLクロス集計クエリ

    追加モジュールtablefuncをインストールします 1回 データベースごとに、関数crosstab()を提供します 。 Postgres 9.1以降、CREATE EXTENSIONを使用できます そのために:

    CREATE EXTENSION IF NOT EXISTS tablefunc;
    

    テストケースの改善

    CREATE TABLE tbl (
       section   text
     , status    text
     , ct        integer  -- "count" is a reserved word in standard SQL
    );
    
    INSERT INTO tbl VALUES 
      ('A', 'Active', 1), ('A', 'Inactive', 2)
    , ('B', 'Active', 4), ('B', 'Inactive', 5)
                        , ('C', 'Inactive', 7);  -- ('C', 'Active') is missing
    

    単純な形式-欠落している属性には適合しません

    crosstab(text) 1 入力パラメータ:

    SELECT *
    FROM   crosstab(
       'SELECT section, status, ct
        FROM   tbl
        ORDER  BY 1,2'  -- needs to be "ORDER BY 1,2" here
       ) AS ct ("Section" text, "Active" int, "Inactive" int);
    

    返品:

     Section | Active | Inactive
    ---------+--------+----------
     A       |      1 |        2
     B       |      4 |        5
     C       |      7 |           -- !!
    
    • キャストや名前の変更は必要ありません。
    • 不正解に注意してください Cの結果 :値7 最初の列に入力されます。この動作が望ましい場合もありますが、このユースケースではそうではありません。
    • 単純な形式も正確にに制限されます 提供された入力クエリの3つの列: row_name カテゴリ追加の列の余地はありません 以下の2パラメータの代替案のように。

    安全なフォーム

    crosstab(text, text) 2 入力パラメータ:

    SELECT *
    FROM   crosstab(
       'SELECT section, status, ct
        FROM   tbl
        ORDER  BY 1,2'  -- could also just be "ORDER BY 1" here
    
      , $$VALUES ('Active'::text), ('Inactive')$$
       ) AS ct ("Section" text, "Active" int, "Inactive" int);

    返品:

     Section | Active | Inactive
    ---------+--------+----------
     A       |      1 |        2
     B       |      4 |        5
     C       |        |        7  -- !!
    
    • Cの正しい結果に注意してください 。

    • 2番目のパラメータ 1つのを返す任意のクエリにすることができます 最後の列定義の順序に一致する属性ごと。多くの場合、次のように、基になるテーブルから個別の属性をクエリする必要があります。

        'SELECT DISTINCT attribute FROM tbl ORDER BY 1'
      

    それはマニュアルにあります。

    とにかく列定義リストのすべての列を詳しく説明する必要があるため(事前定義されたcrosstabN() バリアント)、通常はVALUESで短いリストを提供する方が効率的です 実証されたような表現:

        $$VALUES ('Active'::text), ('Inactive')$$)
    

    または(マニュアルにはありません):

        $$SELECT unnest('{Active,Inactive}'::text[])$$  -- short syntax for long lists
    
    • ドルの見積もりを使用しました 見積もりを簡単にするため。

    • 異なるの列を出力することもできます データ型 crosstab(text, text)を使用 -値列のテキスト表現がターゲットタイプの有効な入力である限り。このようにして、異なる種類の属性を持ち、textを出力することができます。 、datenumeric それぞれの属性についてなど。この章の最後にコード例がありますcrosstab(text, text) マニュアルで。

    db<>ここでフィドル

    過剰な入力行の影響

    過剰な入力行は異なる方法で処理されます-同じ( "row_name"、 "category")の組み合わせに対して重複する行-(section, status) 上記の例では。

    1パラメータ フォームは、使用可能な値の列を左から右に入力します。過剰な値は破棄されます。
    以前の入力行が優先されます。

    2パラメータ formは、各入力値を専用の列に割り当て、以前の割り当てを上書きします。
    後の入力行が優先されます。

    通常、最初から重複することはありません。ただし、そうする場合は、必要に応じて並べ替え順序を慎重に調整し、何が起こっているかを文書化します。
    または、気にしない場合は、任意の結果をすばやく取得します。影響に注意してください。

    高度な例

    • Tablefuncを使用して複数の列をピボットする-前述の「追加の列」も示します

    • CASEおよびGROUPBYを使用したピボットの動的な代替手段


    \crosstabview psqlで

    Postgres 9.6 このメタコマンドをデフォルトのインタラクティブターミナルpsqlに追加しました。最初のcrosstab()として使用するクエリを実行できます パラメータを入力して\crosstabviewにフィードします (すぐにまたは次のステップで)。いいね:

    db=> SELECT section, status, ct FROM tbl \crosstabview
    

    上記と同様の結果ですが、これはクライアント側の表現機能です。 排他的に。入力行の処理は少し異なるため、ORDER BY 必須ではありません。 \crosstabviewの詳細 マニュアルで。そのページの下部に他のコード例があります。

    DanielVérité(psql機能の作成者)によるdba.SEに関する関連回答:

    • 結果のテーブル定義が不明なピボットCROSSJOINを生成するにはどうすればよいですか?


    1. SQL Server(C#クライアント)に大量のデータを一括挿入するための最速の方法は何ですか

    2. CentOS5でMySQLリレーショナルデータベースを使用する

    3. EnterpriseEditionでNOEXPANDヒントを使用するもう1つの理由

    4. SQLServerでsysjobhistoryの日時と期間の列をフォーマットします