Mysql将列转换为行(数据透视表)
Posted
技术标签:
【中文标题】Mysql将列转换为行(数据透视表)【英文标题】:Mysql Convert Column to row (Pivot table ) 【发布时间】:2012-12-06 08:02:15 【问题描述】:我有一张这样的桌子
+---+-----+----+----+----+----+
|id |month|col1|col2|col3|col4|
+---+-----+----+----+----+----+
|101|Jan |A |B |NULL|B |
+---+-----+----+----+----+----+
|102|feb |C |A |G |E |
+---+-----+----+----+----+----+
然后我想创建这样的报告
+----+---+---+
|desc|jan|feb|
+----+---+---+
|col1|A |C |
+----+---+---+
|col2|B |A |
+----+---+---+
|col3|0 |G |
+----+---+---+
|Col4|B |E |
+----+---+---+
有人可以帮忙吗?
【问题讨论】:
欢迎来到***。 This is a very common question。请花几分钟时间搜索档案。尝试先调整以前的答案之一。然后,如果您遇到问题,请在此处发布您的查询和任何错误。 mysql pivot row into dynamic number of columns的可能重复 【参考方案1】:您需要首先对数据进行反透视,然后对其进行透视。但不幸的是,MySQL 没有这些函数,因此您需要使用 UNION ALL
查询 unpivot 和聚合函数以及 CASE
来复制它们。
unpivot 或UNION ALL
部分从您的 col1、col2 等获取数据并将其转换为多行:
select id, month, col1 value, 'col1' descrip
from yourtable
union all
select id, month, col2 value, 'col2' descrip
from yourtable
union all
select id, month, col3 value, 'col3' descrip
from yourtable
union all
select id, month, col4 value, 'col4' descrip
from yourtable
见SQL Fiddle with Demo。
结果:
| ID | MONTH | VALUE | DESCRIP |
----------------------------------
| 101 | Jan | A | col1 |
| 102 | feb | C | col1 |
| 101 | Jan | B | col2 |
| 102 | feb | A | col2 |
| 101 | Jan | (null) | col3 |
| 102 | feb | G | col3 |
| 101 | Jan | B | col4 |
| 102 | feb | E | col4 |
然后您将其包装在子查询中以应用聚合和 CASE
以将其转换为您想要的格式:
select descrip,
max(case when month = 'jan' then value else 0 end) jan,
max(case when month = 'feb' then value else 0 end) feb
from
(
select id, month, col1 value, 'col1' descrip
from yourtable
union all
select id, month, col2 value, 'col2' descrip
from yourtable
union all
select id, month, col3 value, 'col3' descrip
from yourtable
union all
select id, month, col4 value, 'col4' descrip
from yourtable
) src
group by descrip
见SQL Fiddle with demo
结果是:
| DESCRIP | JAN | FEB |
-----------------------
| col1 | A | C |
| col2 | B | A |
| col3 | 0 | G |
| col4 | B | E |
【讨论】:
谢谢你!超级有帮助。 非常感谢。如果yourtable
是来自子查询的派生表怎么办。我会用FROM (SELECT * FROM table WHERE name = 'condition') t1
之类的东西替换每个yourtable
吗?
@Accountantم 是的,这正是你要做的
@Taryn - 你的解决方案太棒了。这对我帮助很大。为您的精彩回答投票。【参考方案2】:
虽然这个问题太老了,有人将其标记为“非常常见”,但人们似乎仍然发现它(包括我)并觉得它很有帮助。我开发了一个更通用的版本来取消旋转一行,并认为它可能对某人有所帮助。
SET @target_schema='schema';
SET @target_table='table';
SET @target_where='`id`=1';
SELECT
GROUP_CONCAT(qry SEPARATOR ' UNION ALL ')
INTO @sql
FROM (
SELECT
CONCAT('SELECT `id`,', QUOTE(COLUMN_NAME), ' AS `key`,`', COLUMN_NAME, '` AS `value` FROM `', @target_table, '` WHERE ', @target_where) qry
FROM (
SELECT `COLUMN_NAME`
FROM `INFORMATION_SCHEMA`.`COLUMNS`
WHERE `TABLE_SCHEMA`=@target_schema
AND `TABLE_NAME`=@target_table
) AS `A`
) AS `B`;
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
我在 MySQL 8.x 服务器上使用此查询并将其聚合到那里的 JSON 对象,因此id, key, value
结果结构。
【讨论】:
以上是关于Mysql将列转换为行(数据透视表)的主要内容,如果未能解决你的问题,请参考以下文章