Mysql将列转换为行(数据透视表)

use*_*516 19 mysql sql pivot unpivot

我有一张这样的桌子

+---+-----+----+----+----+----+
|id |month|col1|col2|col3|col4|
+---+-----+----+----+----+----+
|101|Jan  |A   |B   |NULL|B   |
+---+-----+----+----+----+----+
|102|feb  |C   |A   |G   |E   |
+---+-----+----+----+----+----+
Run Code Online (Sandbox Code Playgroud)

然后我想创建这样的报告

+----+---+---+
|desc|jan|feb|
+----+---+---+
|col1|A  |C  |
+----+---+---+
|col2|B  |A  |
+----+---+---+
|col3|0  |G  |
+----+---+---+
|Col4|B  |E  |
+----+---+---+
Run Code Online (Sandbox Code Playgroud)

有人能帮忙吗?

Tar*_*ryn 41

您需要做的是首先,取消数据的转换,然后转动数据.但遗憾的是MySQL没有这些功能,所以你需要使用UNION ALL对于unpivot 的查询和带有CASEfor的pivot 的聚合函数来复制它们.

unpivot或UNION ALLpiece从您的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
Run Code Online (Sandbox Code Playgroud)

请参阅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 |
Run Code Online (Sandbox Code Playgroud)

然后将其包装在子查询中以应用聚合并将其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
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle with demo

结果是:

| DESCRIP | JAN | FEB |
-----------------------
|    col1 |   A |   C |
|    col2 |   B |   A |
|    col3 |   0 |   G |
|    col4 |   B |   E |
Run Code Online (Sandbox Code Playgroud)


bel*_*xic 5

尽管这个问题非常古老并且有人将其标记为“非常常见”,但人们似乎仍然发现它(包括我)并发现它很有帮助。我开发了一个更通用的版本来取消行的旋转,并认为它可能对某人有帮助。

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;
Run Code Online (Sandbox Code Playgroud)

我在 MySQL 8.x 服务器上使用此查询并将其聚合为 JSON 对象,从而得到id, key, value结果结构。