0

我有一张下表。

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

我需要输出为(条件 LocID = 1)

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

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

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

任何帮助....

4

1 回答 1

8

为了获得您想要的结果,您需要将当前数据从列中转为行,然后将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 |
于 2013-04-07T15:40:23.917 回答