2013-07-31 17 views
5

ここでquestionに続いて、行を列に動的に変換するためのMysqlクエリを使用しています。これはうまく動作しますが、私はこれを2つの列に基づいて変換する必要があります2列に基づいて行を列に動的に変換するMysqlクエリ

上記のリンクで言及されたクエリは、単一の列 "data"で動作しますが、 "data"価格"。

Result Table 

| id|order1|order2|order3|item1|item2|item3|item4| 
-----+-----+--------------------------------------- 
| 1| P | Q |  | 50 | 60 | 70 |  | 
| 2| P |  | S | 50 | 60 |  | 80 | 

I:私は次のようなクエリを書くのが好き

Table A 

| id|order|data|item|Price| 
-----+-----+---------------- 
| 1| 1| P| 1 | 50 | 
| 1| 1| P| 2 | 60 | 
| 1| 1| P| 3 | 70 | 
| 1| 2| Q| 1 | 50 | 
| 1| 2| Q| 2 | 60 | 
| 1| 2| Q| 3 | 70 | 
| 2| 1| P| 1 | 50 | 
| 2| 1| P| 2 | 60 | 
| 2| 1| P| 4 | 80 | 
| 2| 3| S| 1 | 50 | 
| 2| 3| S| 2 | 60 | 
| 2| 3| S| 4 | 80 | 

ように見えるテーブルA、与えられた私はここでは例を追加した

これを達成するために2つの異なるクエリを作成してから結合しようとしましたが、それは良い解決策ではありません。上記のリンクで説明したのと同じ解決策を提案することができます。

おかげ

答えて

15

あなたはorderitem両方の値の既知の数を持っていた場合、あなたはハードにクエリを記述できます。

select id, 
    max(case when `order` = 1 then data end) order1, 
    max(case when `order` = 2 then data end) order2, 
    max(case when `order` = 3 then data end) order3, 
    max(case when item = 1 then price end) item1, 
    max(case when item = 2 then price end) item2, 
    max(case when item = 3 then price end) item3, 
    max(case when item = 4 then price end) item4 
from tableA 
group by id; 

Demoを参照してください。しかし、問題の一部は、データの複数の列を変換しようとしているためです。最終的な結果を得るための私の提案は、まずデータをピボット解除することです。 MySQLにはピボット解除機能はありませんが、UNION ALLを使用して複数の列のペアを行に変換できます。アンピボットのコードは次のようになります。

select id, concat('order', `order`) col, data value 
from tableA 
union all 
select id, concat('item', item) col, price value 
from tableA; 

Demoを参照してください。この結果は以下のようになります。

| ID | COL | VALUE | 
----------------------- 
| 1 | order1 |  P | 
| 1 | order1 |  P | 
| 1 | order1 |  P | 
| 1 | item1 | 50 | 
| 1 | item2 | 60 | 
| 1 | item3 | 70 | 

あなたは、これがorder/dataitem/priceの複数の列をとっている参照して複数の行に変換することができたよう。それが完了したら、あなたはCASEと集計関数を使用して列に戻す値を変換することができます

select id, 
    max(case when col = 'order1' then value end) order1, 
    max(case when col = 'order2' then value end) order2, 
    max(case when col = 'order3' then value end) order3, 
    max(case when col = 'item1' then value end) item1, 
    max(case when col = 'item2' then value end) item2, 
    max(case when col = 'item3' then value end) item3 
from 
(
    select id, concat('order', `order`) col, data value 
    from tableA 
    union all 
    select id, concat('item', item) col, price value 
    from tableA 
) d 
group by id; 

Demoを参照してください。最後に、あなたはダイナミックプリペアドステートメントのクエリに上記のコードを変換する必要があります。

SET @sql = NULL; 
SELECT 
    GROUP_CONCAT(DISTINCT 
    CONCAT(
     'max(case when col = ''', 
     col, 
     ''' then value end) as `', 
     col, '`') 
) INTO @sql 
FROM 
(
    select concat('order', `order`) col 
    from tableA 
    union all 
    select concat('item', `item`) col 
    from tableA 
)d; 

SET @sql = CONCAT('SELECT id, ', @sql, ' 
        from 
        (
        select id, concat(''order'', `order`) col, data value 
        from tableA 
        union all 
        select id, concat(''item'', item) col, price value 
        from tableA 
       ) d 
        group by id'); 

PREPARE stmt FROM @sql; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 

SQL Fiddle with demoを参照してください。結果は次のようになります。

| ID | ORDER1 | ORDER2 | ORDER3 | ITEM1 | ITEM2 | ITEM3 | ITEM4 | 
------------------------------------------------------------------- 
| 1 |  P |  Q | (null) | 50 | 60 |  70 | (null) | 
| 2 |  P | (null) |  S | 50 | 60 | (null) |  80 | 
関連する問題