web-dev-qa-db-ja.com

unpivotとPostgreSQL

PostgreSQLにピボットされていない同等の関数はありますか?

27
Tony Searle

サンプルテーブルを作成します。

_CREATE TEMP TABLE foo (id int, a text, b text, c text);
INSERT INTO foo VALUES (1, 'ant', 'cat', 'chimp'), (2, 'grape', 'mint', 'basil');
_

UNION ALLを使用して、「ピボット解除」または「クロス集計解除」できます。

_SELECT id,
       'a' AS colname,
       a AS thing
FROM foo
UNION ALL
SELECT id,
       'b' AS colname, 
       b AS thing
FROM foo
UNION ALL
SELECT id, 
       'c' AS colname,
       c AS thing
FROM foo
ORDER BY id;
_

これにより、fooで3つの異なるサブクエリが実行されます。1つはピボット解除する列ごとに1つで、1つのテーブルに各サブクエリのすべてのレコードが返されます。

ただし、これによりテーブルがN回スキャンされます。ここで、Nはピボットを解除する列の数です。これは非効率的であり、たとえば、スキャンに長い時間がかかる非常に大きなテーブルで作業している場合に大きな問題になります。

代わりに、以下を使用してください。

_SELECT id,
       unnest(array['a', 'b', 'c']) AS colname,
       unnest(array[a, b, c]) AS thing
FROM foo
ORDER BY id;
_

これは記述が簡単で、テーブルを1回だけスキャンします。

_array[a, b, c]_は、a、b、およびcの値を要素として持つ配列オブジェクトを返します。 unnest(array[a, b, c])は、配列の要素ごとに結果を1つの行に分割します。

お役に立てば幸いです。

83
Stew

VALUES() および JOIN LATERAL 列のピボットを解除します。

サンプルデータ:

CREATE TABLE test(id int, a INT, b INT, c INT);
INSERT INTO test(id,a,b,c) VALUES (1,11,12,13),(2,21,22,23),(3,31,32,33);

クエリ:

SELECT t.id, s.col_name, s.col_value
FROM test t
JOIN LATERAL(VALUES('a',t.a),('b',t.b),('c',t.c)) s(col_name, col_value) ON TRUE;

DBFiddleデモ

このアプローチを使用すると、列の複数のグループを一度にピボット解除することができます。

[〜#〜]編集[〜#〜]

ザックの 提案を使用する:

SELECT t.id, col_name, col_value
FROM test t
CROSS JOIN LATERAL (VALUES('a', t.a),('b', t.b),('c',t.c)) s(col_name, col_value);

<=>

SELECT t.id, col_name, col_value
FROM test t
,LATERAL (VALUES('a', t.a),('b', t.b),('c',t.c)) s(col_name, col_value);

db <>フィドルデモ

5
Lukasz Szozda

RedShiftでピボットを解除する方法を探している私たちのための参考までに。

Stewによって提供された長い形式のソリューションは、これを達成する唯一の方法のようです。

https://forums.aws.Amazon.com/thread.jspa?threadID=126369


見えない方のために、下に貼り付けたテキストがあります...

ピボットまたはアンピボットを実行する組み込み関数はありません。ただし、それを行うためにいつでもSQLを作成できます。

create table sales (regionid integer, q1 integer, q2 integer, q3 integer, q4 integer);
insert into sales values (1,10,12,14,16), (2,20,22,24,26);

select * from sales order by regionid;

regionid | q1 | q2 | q3 | q4
----------+----+----+----+----
1 | 10 | 12 | 14 | 16
2 | 20 | 22 | 24 | 26

(2 rows)

ピボットクエリ

create table sales_pivoted (regionid, quarter, sales)
as
select regionid, 'Q1', q1 from sales
UNION ALL
select regionid, 'Q2', q2 from sales
UNION ALL
select regionid, 'Q3', q3 from sales
UNION ALL
select regionid, 'Q4', q4 from sales
;

select * from sales_pivoted order by regionid, quarter;

regionid | quarter | sales 
----------+---------+-------
1 | Q1 | 10
1 | Q2 | 12
1 | Q3 | 14
1 | Q4 | 16
2 | Q1 | 20
2 | Q2 | 22
2 | Q3 | 24
2 | Q4 | 26
(8 rows)

ピボット解除クエリ

select regionid, sum(Q1) as Q1, sum(Q2) as Q2, sum(Q3) as Q3, sum(Q4) as Q4
from
(select regionid, 
case quarter when 'Q1' then sales else 0 end as Q1,
case quarter when 'Q2' then sales else 0 end as Q2,
case quarter when 'Q3' then sales else 0 end as Q3,
case quarter when 'Q4' then sales else 0 end as Q4
from sales_pivoted)

group by regionid
order by regionid;
regionid | q1 | q2 | q3 | q4 
----------+----+----+----+----
1 | 10 | 12 | 14 | 16
2 | 20 | 22 | 24 | 26
(2 rows)

これがお役に立てば幸い、ニール

4
camacnei

PostgreSQL用の恐ろしいピボット解除関数を作成しました。かなり遅いですが、少なくとも、ピボット解除操作で期待されるような結果が返されます。

https://cgsrv1.arrc.csiro.au/blog/2010/05/14/unpivotuncrosstab-in-postgresql/

うまくいけば、あなたはそれが役に立つと思うことができます。

2
Josh LOL

@a_horse_with_no_nameからのコメント内のリンクからわずかに変更されたコンテンツを、機能するために回答にプルします。

Hstoreのインストール
hstoreがインストールされておらず、PostgreSQL 9.1以降を実行している場合は、便利なものを使用できます。

CREATE EXTENSION hstore;

下位バージョンの場合は、hstore.sqlshare/contribファイルを探し、データベースで実行します。

ソース(ワイドデータなど)テーブルにid_fieldという名前の「id」列が1つと、すべて同じタイプの「value」列がいくつもあるとすると、次のようにすると、そのテーブルのピボットされていないビューが作成されます。 。

CREATE VIEW vw_unpivot 
AS 
SELECT id_field, (h).key AS column_name, (h).value AS column_value
  FROM (SELECT id_field, each(hstore(foo) - 'id_field'::text) AS h
          FROM zcta5 as foo  
       ) AS unpiv ; 

これは、任意の数の「値」列で機能します。 (h).value::numericのようにキャストしない限り、結果の値はすべてテキストになります。

1
Brian D