Mysql
 sql >> Base de données >  >> RDS >> Mysql

Requête MySQL pour convertir dynamiquement des lignes en colonnes sur la base de deux colonnes

Si vous aviez un nombre connu de valeurs pour les deux order et item , vous pouvez alors coder en dur la requête dans :

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;

Voir Démo . Mais une partie du problème que vous allez rencontrer est que vous essayez de transformer plusieurs colonnes de données. Ma suggestion pour obtenir le résultat final serait de d'abord désorienter les données. MySQL n'a pas de fonction unpivot mais vous pouvez utiliser un UNION ALL pour convertir les multiples paires de colonnes en lignes. Le code pour annuler le pivot sera similaire à ce qui suit :

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

Voir Démo . Le résultat sera :

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

Comme vous pouvez le voir, cela a pris les multiples colonnes de order /data et item /price et convertissez-le en plusieurs lignes. Une fois cette opération terminée, vous pouvez reconvertir les valeurs en colonnes à l'aide d'une fonction d'agrégation avec un 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;

Voir Démo . Enfin, vous devez convertir le code ci-dessus en une requête d'instruction préparée dynamique :

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;

Voir SQL Fiddle avec démo . Cela donne un résultat :

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