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

vx6bjr1n  于 2023-03-07  发布在  Mysql
关注(0)|答案(3)|浏览(150)

我有一张这样的table
| 身份证|月|列1|列2|第3栏|第4栏|
| - ------|- ------|- ------|- ------|- ------|- ------|
| 一百零一|一月|A类|B|零|B|
| 一百零二|二月|C级|A类|G级|E级|
然后我想创建这样的报告
| 描述|扬|二月|
| - ------|- ------|- ------|
| 列1|A类|C级|
| 列2|B|A类|
| 第3栏|无|G级|
| 第4列|B|E级|
有人能帮忙吗?

pprl5pva

pprl5pva1#

您需要做的是首先对数据进行反透视,然后再进行透视,但不幸的是MySQL没有这些函数,因此您需要使用UNION ALL查询来进行反透视,使用聚合函数CASE来进行透视。
解透视或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演示。
结果:

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

然后将其 Package 在子查询中以应用聚合和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演示
结果是:

| DESCRIP | JAN | FEB |
-----------------------
|    col1 |   A |   C |
|    col2 |   B |   A |
|    col3 |   0 |   G |
|    col4 |   B |   E |
wz1wpwve

wz1wpwve2#

虽然这个问题已经很老了,而且有人把它标为“非常常见”,但人们似乎仍然发现它(包括我),并发现它很有帮助。我开发了一个更通用的版本来取消透视一行,并认为它可能对某些人有帮助。

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结果结构。

zxlwwiss

zxlwwiss3#

(* 扩展this great previous answer,因为目前我的帐户无法编辑或评论
尽管这种方法不像以前的UNION ALL / CASE -方法那样简单,但它的优点在于可以(“动态地”)用于任何数量的原始列[* 请更正“任何”*]。
可能导致不明确错误的限制是
group_concat_max_len
系统变量,默认值为1024
在这种情况下,请尝试以下操作

SET SESSION group_concat_max_len = 92160;

相关问题