我有下表。
/------------------------------------\
| 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年(将给予年度2012年,然后需要显示2011年和2012年)。
基本上需要将列名称作为行值,将列值作为列标题...
任何帮助......
答案 0 :(得分: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。代码类似于以下内容:
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 |