简体   繁体   English

Mysql查询在两列的基础上动态地将行转换为列

[英]Mysql query to dynamically convert rows to columns on the basis of two columns

I have followed a question here to use a Mysql query to dynamically convert rows to columns. 我在这里跟着一个问题 ,使用Mysql查询动态地将行转换为列。 This works fine, but i need to convert this on basis of two columns, 这工作正常,但我需要在两列的基础上转换它,

The query mentioned in above link works for a single column "data", but i want to work for two columns which are "data" and "price". 上面链接中提到的查询适用于单个列“数据”,但我想工作两列“数据”和“价格”。

i have added an example here, 我在这里添加了一个例子,

Given a table A, which look like 给出表A,看起来像

Table A

|  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  |

I like to write a query that looks like the following: 我想编写一个如下所示的查询:

Result Table

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

I have tried to create two different queries and then a join to achieve this, but that may not be a good solution. 我试图创建两个不同的查询然后连接来实现这一点,但这可能不是一个好的解决方案。 Can any one suggest a solution same like mentioned in the link above. 任何人都可以提出与上述链接中提到的相同的解决方案。

Thanks 谢谢

If you had a known number of values for both order and item , then you could hard code the query into: 如果您有orderitem的已知数量的值,那么您可以将查询硬编码为:

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;

See Demo . 演示 But part of the problem that you are going to have is because you are trying to transform multiple columns of data. 但是你要遇到的部分问题是因为你试图转换多列数据。 My suggestion to get the final result would be to unpivot the data first. 我得到最终结果的建议是先将数据取消。 MySQL does not have an unpivot function but you can use a UNION ALL to convert the multiple pairs of columns into rows. MySQL没有unpivot函数,但您可以使用UNION ALL将多对列转换为行。 The code to unpivot will be similar to the following: 取消移动的代码将类似于以下内容:

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

See Demo . 演示 The result of this will be: 结果将是:

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

As you can see this has taken the multiple columns of order / data and item / price and convert it into multiple rows. 如您所见,这已经采用了多列order / dataitem / price并将其转换为多行。 Once that is completed, then you can convert the values back into columns using an aggregate function with a CASE: 完成后,您可以使用带有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;

See Demo . 演示 Finally, you need to convert the above code into a dynamic prepared statement query: 最后,您需要将上面的代码转换为动态预准备语句查询:

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;

See SQL Fiddle with demo . 请参阅SQL Fiddle with demo This gives a result: 这给出了一个结果:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM