特別な問題は、データがクロス集計の準備ができていないことです。 row_nameの形式のデータが必要です 、カテゴリ 、値 。 UNION
でそれを得ることができます クエリ:
SELECT 'metric1' AS metric, country_code, metric1 FROM tbl1
UNION ALL
SELECT 'metric2' AS metric, country_code, metric2 FROM tbl1
UNION ALL
SELECT 'metric3' AS metric, country_code, metric3 FROM tbl1
ORDER BY 1, 2 DESC;
しかし、賢いLATERAL
クエリは1回のテーブルスキャンのみを必要とし、より高速になります:
SELECT x.metric, t.country_code, x.val
FROM tbl1 t
, LATERAL (VALUES
('metric1', metric1)
, ('metric2', metric2)
, ('metric3', metric3)
) x(metric, val)
ORDER BY 1, 2 DESC;
関連:
crosstab()
の単純な形式を使用する このクエリを入力として1つのパラメータを使用:
SELECT * FROM crosstab(
$$SELECT x.metric, t.country_code, x.val
FROM tbl1 t
, LATERAL (VALUES
('metric1', metric1)
, ('metric2', metric2)
, ('metric3', metric3)
) x(metric, val)
ORDER BY 1, 2 DESC$$
)
AS ct (metric text, us int, uk int, fr int);
国名をアルファベットの降順でリストします(デモのように)。これは、すべてのメトリックがNOT NULL
で定義されていることも前提としています。 。
一方または両方が当てはまらない場合は、代わりに2パラメータ形式を使用してください。
「ロールアップ」を追加
つまりメトリックごとの合計:
SELECT * FROM crosstab(
$$SELECT x.metric, t.country_code, x.val
FROM (
TABLE tbl1
UNION ALL
SELECT 'zzz_total', sum(metric1)::int, sum(metric2)::int, sum(metric3)::int -- etc.
FROM tbl1
) t
, LATERAL (VALUES
('metric1', metric1)
, ('metric2', metric2)
, ('metric3', metric3)
) x(metric, val)
ORDER BY 1, 2 DESC$$
)
AS ct (metric text, total int, us int, uk int, fr int);
'zzz_total'
は任意のラベルであり、最後にアルファベット順に並べ替える必要があります(または、crosstab()
の2パラメーター形式が必要です 。
たくさんある場合 メトリック列の場合、クエリ文字列を動的に作成することをお勧めします。関連:
また、次のPostgres 9.5(現在はベータ版)では、専用の ROLLUP
のSQL句
。
関連: