2013-04-04 65 views
0

我有一个下表。MySQL中的动态查询

/------------------------------------\ 
| 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年(今年将给予2012年的前期,然后需要显示2011年和2012年)。

本质上需要作出列名作为行值和列值列标题...

任何帮助....

+0

请修改您的问题 – Kasnady 2013-04-04 07:59:21

+0

您想使用哪种语言? – chintan 2013-04-04 08:03:40

+0

可能重复的[MySQL数据透视行到动态数列](http://stackoverflow.com/questions/12004603/mysql-pivot-row-into-dynamic-number-of-columns) – RichardTheKiwi 2013-05-03 09:02:07

回答

7

为了得到你想要的结果,你需要将当前数据从列转换为行,然后将行中的数据转换为列。

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 |