Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL-Abfrage zum dynamischen Konvertieren von Zeilen in Spalten auf der Grundlage von zwei Spalten

Wenn Sie eine bekannte Anzahl von Werten für beide order hatten und item , dann könnten Sie die Abfrage fest codieren 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;

Siehe Demo . Aber ein Teil des Problems, das Sie haben werden, besteht darin, dass Sie versuchen, mehrere Datenspalten zu transformieren. Mein Vorschlag, um das Endergebnis zu erhalten, wäre, die Daten zuerst zu entpichten. MySQL hat keine Unpivot-Funktion, aber Sie können UNION ALL verwenden, um die mehreren Spaltenpaare in Zeilen umzuwandeln. Der Code zum Entpivotieren sieht etwa so aus:

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

Siehe Demo . Das Ergebnis davon wird sein:

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

Wie Sie sehen können, hat dies die mehreren Spalten von order in Anspruch genommen /data und item /price und in mehrere Zeilen umwandeln. Sobald dies abgeschlossen ist, können Sie die Werte mithilfe einer Aggregatfunktion mit einem CASE:

wieder in Spalten konvertieren
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;

Siehe Demo . Schließlich müssen Sie den obigen Code in eine dynamische vorbereitete Anweisungsabfrage umwandeln:

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;

Siehe SQL Fiddle mit Demo . Dies ergibt ein Ergebnis:

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