2013-07-31 19 views
5

Ho seguito uno question qui per utilizzare una query Mysql per convertire dinamicamente le righe in colonne. Funziona bene, ma ho bisogno di convertirlo in base a due colonne,Query Mysql per convertire dinamicamente le righe in colonne sulla base di due colonne

La query menzionata nel link sopra funziona per una singola colonna "dati", ma voglio lavorare per due colonne che sono "dati" e " prezzo".

ho aggiunto un esempio qui,

Data una tabella A, che sembro

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 | 

mi piace scrivere una query che è simile al seguente:

Result Table 

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

I ho provato a creare due query diverse e quindi un join per raggiungere questo obiettivo, ma potrebbe non essere una buona soluzione. Qualcuno può suggerire una soluzione come menzionato nel link qui sopra.

Grazie

risposta

15

Se si ha un numero noto di valori sia per order e item, allora si potrebbe difficile codificare la query in:

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; 

Vedi Demo. Ma parte del problema che si sta per avere è perché si sta tentando di trasformare più colonne di dati. Il mio suggerimento per ottenere il risultato finale sarebbe quello di aprire prima i dati. MySQL non ha una funzione unpivot, ma puoi usare UNION ALL per convertire più coppie di colonne in righe. Il codice per UNPIVOT sarà simile al seguente:

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

Vedi Demo. Il risultato di questo sarà:

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

Come si può vedere questo ha preso le colonne multiple di order/data e item/price e convertirlo in più righe. Una volta completata, quindi è possibile convertire i valori di nuovo in colonne utilizzando una funzione di aggregazione con un caso:

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; 

Vedi Demo. Infine, è necessario convertire il codice sopra in una query di dichiarazione preparata dinamica:

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; 

Vedi SQL Fiddle with demo. Questo dà un risultato:

| ID | ORDER1 | ORDER2 | ORDER3 | ITEM1 | ITEM2 | ITEM3 | ITEM4 | 
------------------------------------------------------------------- 
| 1 |  P |  Q | (null) | 50 | 60 |  70 | (null) | 
| 2 |  P | (null) |  S | 50 | 60 | (null) |  80 | 
Problemi correlati