3

次のレイアウトのテーブルがあります。

 ID   Label   Value
 --   -----   -----
 1    Lab1    Value1-1
 1    Lab2    Value1-2
 1    Lab3    Value1-3
 1    Lab4    Value1-4
 1    Lab5    Value1-5
 1    Lab6    Value1-6
 2    Lab1    Value2-1
 2    Lab2    Value2-2
 2    Lab3    Value2-3
 2    Lab4    Value2-4
 2    Lab5    Value2-5
 2    Lab6    Value2-6
 ...

テーブルを次のようにレイアウトするように変換したいと思います。

 ID   Lab1      Lab2       Lab3       Lab4       Lab5       Lab6
 1    Value1-1  Value1-2   Value1-3   Value1-4   Value1-5   Value1-6
 2    Value2-1  Value2-2   Value2-3   Value2-4   Value2-5   Value2-6
 ...

PostgreSQL で SQL を使用しています。これを行う簡単な(そしてメモリ効率の良い)方法はありますか?ピボットの使用について言及している投稿を見たことがありますが、それが機能するかどうかはわかりません。私が見た説明は Oracle に固有のもののようです。

4

2 に答える 2

3

まだインストールしていない場合は、最初に拡張テーブル機能をインストールします。データベースごとに1回実行する必要があります。

CREATE EXTENSION tablefunc;

にはPostgreSQL9.1が必要ですCREATE EXTENSION。古いバージョンでは、次のようなコマンドを使用して、シェルからインストールスクリプトを実行する必要があります。

psql -d dbname -f SHAREDIR/contrib/tablefunc.sql

細かいマニュアルでPostgres9.0の詳細をご覧ください。

次に、次のようなクエリを使用できます。

SELECT *
FROM   crosstab (
    'SELECT id
           ,label
           ,value
     FROM   t
     ORDER  BY 1, 2',

    'SELECT DISTINCT label
     FROM   t
     ORDER  BY 1')
AS tbl (
 id   int
,lab1 text
,lab2 text
,lab3 text
,lab4 text
,lab5 text
,lab6 text
);

要求したものを正確に返します。
そのための関数を作成することもできます。この密接に関連する回答にさらに情報を追加しました。

于 2012-04-21T22:37:24.187 に答える
0

SQL 実装に転置 / クロス集計機能がない場合は、次の方法で EAV をアンロール / 非正規化することもできます。

SET search_path='tnp';

-- create some data ...
CREATE TABLE value
        ( id INTEGER NOT NULL
        , attribute varchar
        , value varchar
        , PRIMARY KEY (id,attribute)
        );
INSERT INTO value(id,attribute,value) VALUES
 (1    ,'Lab1', 'Value1-1' )
 , (1    ,'Lab2', 'Value1-2' )
 , (1    ,'Lab3', 'Value1-3' )
 , (1    ,'Lab4', 'Value1-4' )
 , (1    ,'Lab5', 'Value1-5' )
 , (1    ,'Lab6', 'Value1-6' )
 , (2    ,'Lab1', 'Value2-1' )
 , (2    ,'Lab2', 'Value2-2' )
 , (2    ,'Lab3', 'Value2-3' )
 , (2    ,'Lab4', 'Value2-4' )
 , (2    ,'Lab5', 'Value2-5' )
 , (2    ,'Lab6', 'Value2-6' )
        ;

SELECT v.id
        , l1.value AS lab1
        , l2.value AS lab2
        , l3.value AS lab3
        , l4.value AS lab4
        , l5.value AS lab5
        , l6.value AS lab6
FROM value v
LEFT JOIN value l1 ON l1.id = v.id AND l1.attribute = 'Lab1'
LEFT JOIN value l2 ON l2.id = v.id AND l2.attribute = 'Lab2'
LEFT JOIN value l3 ON l3.id = v.id AND l3.attribute = 'Lab3'
LEFT JOIN value l4 ON l4.id = v.id AND l4.attribute = 'Lab4'
LEFT JOIN value l5 ON l5.id = v.id AND l5.attribute = 'Lab5'
LEFT JOIN value l6 ON l6.id = v.id AND l6.attribute = 'Lab6'
        ;

私は同意します。これはあまりエレガントではありません。しかし、それは機能します。

于 2012-05-27T22:22:03.807 に答える