【问题标题】:Dynamic Query in MySQLMySQL 中的动态查询
【发布时间】:2013-03-26 04:39:34
【问题描述】:

我有一张下表。

/------------------------------------\
| LocID | Year | Birth | Death | Abc |
|------------------------------------|
|  1    | 2011 | 100   | 60    | 10  |
|------------------------------------|
|  1    | 2012 | 98    | 70    | 20  |
|.....                               |
\------------------------------------/

我需要输出为 (Condition LocID = 1)

/---------------------\
| Event | 2011 | 2012 |
|---------------------|
| Birth |  100 |  98  |
|---------------------|
| Death |  60  |  70  |
|---------------------|
| Abc   |  10  |  20  |
\---------------------/

根据各种要求,表格可能包含更多字段...因此行数将取决于字段数(忽略 LOCID 和 YEAR)。列是恒定的。 仅2年(Year will given For ex 2012 is given,然后需要显示2011和2012)。

基本上需要将列名作为行值,将列值作为列标题...

任何帮助....

【问题讨论】:

标签: mysql dynamic pivot unpivot


【解决方案1】:

为了获得您想要的结果,您需要将当前数据从列unpivot转换为行,然后将year 数据从行转换为列。

MySQL 没有 PIVOT 或 UNPIVOT 函数,因此您需要使用 UNION ALL 查询来取消透视,并使用带有 CASE 表达式的聚合函数来进行透视。

如果您有已知数量的值,那么您可以像这样对值进行硬编码:

select locid,
  event,
  max(case when year = 2011 then value end) `2011`,
  max(case when year = 2012 then value end) `2012`
from
(
  select LocId, Year, 'Birth' event, Birth value
  from yt
  union all
  select LocId, Year, 'Death' event, Death value
  from yt
  union all
  select LocId, Year, 'Abc' event, Abc value
  from yt
) d
group by locid, event;

SQL Fiddle with Demo

但是,如果您要拥有未知数量的值,那么您将需要使用准备好的语句来生成动态 SQL。代码将类似于以下内容:

SET @sql = NULL;
SET @sqlUnpiv = NULL;
SET @sqlPiv = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'select locid, year, ''',
      c.column_name,
      ''' as event, ',
      c.column_name,
      ' as value 
      from yt '
    ) SEPARATOR ' UNION ALL '
  ) INTO @sqlUnpiv
FROM information_schema.columns c
where c.table_name = 'yt'
  and c.column_name not in ('LocId', 'Year')
order by c.ordinal_position;

SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'max(CASE WHEN year = ',
      year,
      ' THEN value else null END) AS `',
      year, '`'
    )
  ) INTO @sqlPiv
FROM yt;

SET @sql 
  = CONCAT('SELECT locid,
              event, ', @sqlPiv, ' 
            from 
            ( ',  @sqlUnpiv, ' ) d
            group by locid, event');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SQL Fiddle with Demo。两个查询的结果是:

| LOCID | EVENT | 2011 | 2012 |
-------------------------------
|     1 |   Abc |   10 |   20 |
|     1 | Birth |  100 |   98 |
|     1 | Death |   60 |   70 |

【讨论】:

  • 很好的答案,我知道他的答案很旧,我在寻找重复的时候发现了这个。但它可能有一个缺陷。GROUP_CONCAT 默认设置为最多 1024 个字符,你需要做到这一点更大的SET SESSION group_concat_max_len = @@max_allowed_packet; 例如
猜你喜欢
  • 2015-10-01
  • 2019-01-23
  • 1970-01-01
  • 2013-05-08
  • 2021-08-05
  • 2016-08-06
  • 1970-01-01
  • 1970-01-01
  • 2015-02-18
相关资源
最近更新 更多