2013-04-04 105 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 |