sql >> Database teknologi >  >> RDS >> Mysql

Mysql-forespørgsel til dynamisk at konvertere rækker til kolonner på basis af to kolonner

Hvis du havde et kendt antal værdier for begge order og item , så kan du hårdkode forespørgslen til:

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 af problemet, du vil have, er, fordi du forsøger at transformere flere kolonner af data. Mit forslag til at få det endelige resultat ville være at deaktivere dataene først. MySQL har ikke en unpivot-funktion, men du kan bruge en UNION ALL til at konvertere flere kolonnepar til rækker. Koden til at fjerne pivot vil ligne følgende:

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 af dette vil være:

| 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 dette taget de mange kolonner i order /data og item /price og konverter det til flere rækker. Når det er fuldført, kan du konvertere værdierne tilbage til kolonner ved hjælp af en aggregeret funktion med en 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 . Til sidst skal du konvertere ovenstående kode til en dynamisk forberedt sætningsforespørgsel:

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 Fiddle with demo . Dette giver et 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. Hvordan vælger man en understreng i Oracle SQL op til et bestemt tegn?

  2. Sådan filtreres rækker uden NULL i en kolonne

  3. Java JDBC ignorerer setFetchSize?

  4. Sådan skriver du det første bogstav i hvert ord i PostgreSQL