sql >> Database >  >> RDS >> Mysql

Mysql-query om rijen dynamisch naar kolommen te converteren op basis van twee kolommen

Als u een bekend aantal waarden had voor beide order en item , dan kunt u de query hard coderen 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;

Zie Demo . Maar een deel van het probleem dat u zult hebben, is omdat u meerdere kolommen met gegevens probeert te transformeren. Mijn suggestie om het uiteindelijke resultaat te krijgen, zou zijn om de gegevens eerst ongedaan te maken. MySQL heeft geen unpivot-functie, maar u kunt een UNION ALL gebruiken om de meerdere paren kolommen in rijen om te zetten. De code om het draaien ongedaan te maken is als volgt:

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

Zie Demo . Het resultaat hiervan is:

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

Zoals je kunt zien heeft dit de meerdere kolommen van order . ingenomen /data en item /price en zet het om in meerdere rijen. Zodra dat is voltooid, kunt u de waarden terug naar kolommen converteren met behulp van een aggregatiefunctie met een 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;

Zie Demo . Ten slotte moet u de bovenstaande code omzetten in een dynamisch voorbereide instructiequery:

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;

Zie SQL Fiddle met demo . Dit geeft een resultaat:

| 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. GET_FORMAT() Voorbeelden – MySQL

  2. Hoe zie ik actieve SQL Server-verbindingen?

  3. Oracle:SQL-query om alle triggers te vinden die bij de tabellen horen?

  4. 4 manieren om de tijdzone in Oracle te wijzigen