2013-07-31 60 views
5

我在這裏遵循question來使用Mysql查詢來動態地將行轉換爲列。這工作正常,但我需要在兩列的基礎上進行轉換,在兩列的基礎上動態地將行轉換爲列的Mysql查詢

上面提到的查詢鏈接適用於單列「數據」,但我想工作的兩列是「數據」和「價錢」。

我添加了一些在這裏的例子,

給定一個表A,它看起來像

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 | 

我喜歡寫一個查詢,如下所示:

Result Table 

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

我試圖創建兩個不同的查詢,然後創建一個連接來實現這一點,但這可能不是一個好的解決方案。任何人都可以提出一個解決方案,就像上面鏈接中提到的一樣。

感謝

回答

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不具有unpivot功能,但可以使用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 |