Home >Database >Mysql Tutorial >How to Dynamically Convert Rows to Columns in MySQL Based on Multiple Columns?

How to Dynamically Convert Rows to Columns in MySQL Based on Multiple Columns?

Susan Sarandon
Susan SarandonOriginal
2024-12-29 14:22:11763browse

How to Dynamically Convert Rows to Columns in MySQL Based on Multiple Columns?

Dynamic Conversion of Rows to Columns Based on Multiple Columns in MySQL

In a previous question, a MySQL query was used to dynamically convert rows to columns for a single column. Now, we aim to achieve the same result for two columns: "data" and "price."

Problem:

Convert the data in the following table into columns named "order1," "order2," "order3," "item1," "item2," "item3," and "item4" based on the "order" and "item" columns.

id order data item Price
1 1 P 1 50
1 1 P 2 60
1 1 P 3 70
1 2 Q 1 50
1 2 Q 2 60
1 2 Q 3 70
2 1 P 1 50
2 1 P 2 60
2 1 P 4 80
2 3 S 1 50
2 3 S 2 60
2 3 S 4 80

Desired Result:

id order1 order2 order3 item1 item2 item3 item4
1 P Q 50 60 70
2 P S 50 60 80

Solution:

While a hard-coded query could be used if the number of "order" and "item" values is known, a more dynamic solution is required in the general case.

Unpivoting the Data:

MySQL lacks an unpivot function, but a UNION ALL can be used to convert the multiple data pairs into rows:

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

Converting Values Back into Columns:

The unpivoted data can then be converted back into columns using an aggregate function with 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;

Dynamic Prepared Statement:

Finally, the query can be converted into a dynamic prepared statement using set-based concatenation and EXECUTE:

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;

This approach provides a flexible and dynamic way to convert rows to columns based on multiple criteria in MySQL.

The above is the detailed content of How to Dynamically Convert Rows to Columns in MySQL Based on Multiple Columns?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn