これはcrosstab()
で行うことができます 追加のモジュールtablefuncから:
SELECT b
, COALESCE(a1, 0) AS "A1"
, COALESCE(a2, 0) AS "A2"
, COALESCE(a3, 0) AS "A3"
, ... -- all the way up to "A30"
FROM crosstab(
'SELECT colb, cola, 1 AS val FROM matrix
ORDER BY 1,2'
, $$SELECT 'A'::text || g FROM generate_series(1,30) g$$
) AS t (b text
, a1 int, a2 int, a3 int, a4 int, a5 int, a6 int
, a7 int, a8 int, a9 int, a10 int, a11 int, a12 int
, a13 int, a14 int, a15 int, a16 int, a17 int, a18 int
, a19 int, a20 int, a21 int, a22 int, a23 int, a24 int
, a25 int, a26 int, a27 int, a28 int, a29 int, a30 int);
NULL
の場合 0
の代わりに 動作します。SELECT *
にすることもできます。 外側のクエリで。
詳細な説明:
- PostgreSQLクロス集計クエリ
ここでの特別な「難しさ」:実際の「価値」はありません。したがって、1 AS val
を追加します 最後の列として。
不明な数のカテゴリ
完全に動的なクエリ(結果タイプが不明)は、単一のクエリでは不可能です。 2つが必要です クエリ。最初に上記のようなステートメントを動的に作成してから実行します。詳細:
-
単一のSQLステートメントを使用して複数のmax()値を選択する
-
PostgreSQLは列を行に変換しますか?転置しますか?
-
PostgreSQLでクロス集計用の列を動的に生成する
-
CASEおよびGROUPBYを使用したピボットの動的な代替手段
カテゴリが多すぎます
列の最大数(1600)を超えると、結果を個々の列で表すことができないため、従来のクロス集計は不可能になります。 (また、人間の目は、これほど多くの列を持つテーブルを読み取ることはほとんどできません)
hstore
のような配列またはドキュメントタイプ またはjsonb
代替手段です。配列を使用したソリューションは次のとおりです。
SELECT colb, array_agg(cola) AS colas
FROM (
SELECT colb, right(colb, -1)::int AS sortb
, CASE WHEN m.cola IS NULL THEN 0 ELSE 1 END AS cola
FROM (SELECT DISTINCT colb FROM matrix) b
CROSS JOIN (SELECT DISTINCT cola FROM matrix) a
LEFT JOIN matrix m USING (colb, cola)
ORDER BY sortb, right(cola, -1)::int
) sub
GROUP BY 1, sortb
ORDER BY sortb;
-
次のコマンドで値の完全なグリッドを作成します:
(SELECT DISTINCT colb FROM matrix) b CROSS JOIN (SELECT DISTINCT cola FROM matrix) a
-
LEFT JOIN
既存の組み合わせ、名前の数値部分で並べ替え、配列に集約します。-
right(colb, -1)::int
'A3'から主役をトリミングし、数字を整数にキャストして、適切なソート順を取得します。
-
基本マトリックス
0
のテーブルが必要な場合 1
ここで、x = y
、これはもっと安くすることができます:
SELECT x, array_agg((x = y)::int) AS y_arr
FROM generate_series(1,10) x
, generate_series(1,10) y
GROUP BY 1
ORDER BY 1;
SQLフィドル コメントで提供したものに基づいて構築します。
sqlfiddle.comには現在、配列値の表示を強制終了するバグがあることに注意してください。だから私はtext
にキャストしました それを回避するためにそこにあります。