追加モジュール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
を出力することができます。 、date
、numeric
それぞれの属性についてなど。この章の最後にコード例があります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を生成するにはどうすればよいですか?