sql >> Databasteknik >  >> RDS >> Mysql

Mysql-fråga för att dynamiskt konvertera rader till kolumner på basis av två kolumner

Om du hade ett känt antal värden för båda order och item , då kan du hårdkoda frågan till:

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;

Se Demo . Men en del av problemet som du kommer att ha är att du försöker transformera flera kolumner med data. Mitt förslag för att få det slutliga resultatet skulle vara att avpivota data först. MySQL har ingen unpivot-funktion men du kan använda en UNION ALL för att konvertera flera kolumnpar till rader. Koden för att ta bort pivot kommer att likna följande:

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

Se Demo . Resultatet av detta blir:

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

Som du kan se har detta tagit de många kolumnerna i order /data och item /price och konvertera den till flera rader. När det är klart kan du konvertera värdena tillbaka till kolumner med hjälp av en aggregatfunktion med ett 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;

Se Demo . Slutligen måste du konvertera ovanstående kod till en dynamisk förberedd satsfråga:

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;

Se SQL-fiol med demo . Detta ger ett resultat:

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



  1. Hur man håller reda på vad användarna gör

  2. Guide till designdatabas för kalenderhändelse och påminnelse i MySQL

  3. ETL vs ELT:Vi bestämmer, du dömer

  4. psql - spara resultat av kommandot till en fil