テーブルに次のデータを含める:
ID Category Value
1234 Cat01 V001
1234 Cat02 V002
1234 Cat03 V003
1234 Cat03 V004
1234 Cat03 V005
次の出力が必要です。
ID Cat01 Cat02 Cat03
1234 V001 V002 V003
1234 V001 V002 V004
1234 V001 V002 V005
私が達成したい出力は、テーブルにすべての値を垂直方向に持ち、これらの値を水平方向に、カテゴリを列として持つ、一種のピボットテーブルです。しかし、複数の値を持ついくつかのカテゴリがあります。その場合、他のすべてのカテゴリの値を繰り返し、繰り返される値ごとに行を作成する必要があります
PostgreSQLではどのように実行できますか?
これはトリッキーです。 crosstab()
は one (またはno) value per category を期待します各 row_name 。
この制限は次のように回避できます。
_SELECT id
, COALESCE(cat01, max(cat01) OVER w)
, COALESCE(cat02, max(cat02) OVER w)
, COALESCE(cat03, max(cat03) OVER w)
FROM crosstab(
'SELECT id::text || row_number() OVER (PARTITION BY id, category ORDER BY value) * -1 AS ext_id
, id, category, value
FROM tbl
ORDER BY ext_id, category, value'
,$$VALUES ('Cat01'::text), ('Cat02'), ('Cat03')$$
) AS ct (xid text, id int, cat01 text, cat02 text, cat03 text)
WINDOW w AS (PARTITION BY id);
_
希望する結果を返します。
既存のid
からの拡張ID _ext_id
_と、同じid
のカテゴリの各値の行番号を追加します。このようにして、最も一般的なカテゴリの値と同じ数のid
あたりの行を確保します。次のような派生テーブルを取得して、crosstab()
を作成します。
_ext_id | id | category | value
---------+------+----------+-------
'1234-1' | 1234 | 'Cat01' | 'V001'
'1234-1' | 1234 | 'Cat02' | 'V002'
'1234-1' | 1234 | 'Cat03' | 'V003'
'1234-2' | 1234 | 'Cat03' | 'V004'
'1234-3' | 1234 | 'Cat03' | 'V005'
_
これで、不足している属性の安全な2パラメータフォームを使用してcrosstab()
にフィードできます。これに慣れていない場合は、まず基本を読んでください。
元のid
は「追加の列」として引き継がれます。見る:
あなたの質問は解釈の余地を残します。私のソリューションでは、カテゴリごとに lowest の値を最初にペアにし、値がなくなるまで次の行を埋めていきます。 (他の方法でカテゴリごとに複数の値を組み合わせることができますが、定義されていません。)特定のid
の値がカテゴリに不足している場合、残りはNULL値で埋められます。
最後のステップで、これらのNULL値をcategory
ごとの各id
の最大値に置き換えます。
_COALESCE(cat01, max(cat01) OVER (PARTITION BY id, category))
_
これは事実上次と同じです:
_max(cat01) OVER (PARTITION BY id, category)
_
値がNULLの場合にデフォルトでウィンドウ関数のみを使用する場合は、少し速くなることを期待しています。
CROSSTAB
関数の使用例については、 ここ をご覧ください。また、同じスレッドでのErwin Brandstetterの投稿とリンク(特に、「基本的なcrosstab():」リンク)をよく見てください。
NULL
sに注意してください(リンクの説明を参照)。
ソースからコンパイルされたPostgreSQLバージョンを使用していない場合、CROSSTAB
関数にアクセスするために必要なのは入力することだけです。
CREATE EXTENSION tablefunc;
コマンドライン(EBリンクを参照)。
あなたの補足情報を完全に把握したかどうかはわかりませんが、おそらく私がクロスジョインステータスとスロット(カテゴリと値に相当するもの)をクロスさせるために使用したCTEアプローチが役立つかもしれません。そうでない場合は、コメントを拡張してください。 EBのコードも役立つかもしれません。