MySQL基本表旋转

时间:2013-04-20 19:37:16

标签: mysql sql pivot

我正在尝试调整一个看似.....的表结果。

     -----------------------------------------------
    | personsID    |   personsWeight |  dateWeighed |
     -----------------------------------------------
    |          1   |      160        |   04/15/2011 |
     -----------------------------------------------
    |          1   |      161        |   04/18/2011 |
     -----------------------------------------------
    |          1   |      162        |   06/30/2011 |
     -----------------------------------------------
    |          1   |      163        |   07/11/2011 |
     -----------------------------------------------
    |          1   |      164        |   04/01/2012 |
     -----------------------------------------------

我希望它看起来像

     --------------------------------------------------------------------------------
    |  personsID   | 04/15/2011  | 04/18/2011 | 06/30/2011 | 07/11/2011 | 04/01/2012 |
     --------------------------------------------------------------------------------
    |        1     |     160     |   161      |     162    |     163    |    164     |
     --------------------------------------------------------------------------------

1 个答案:

答案 0 :(得分:1)

MySQL没有PIVOT函数,因此您必须使用带有CASE表达式的聚合函数将数据行转换为列。

如果您有一组数字或已知数量的值,那么您可以对查询进行硬编码:

select personsId,
  sum(case when dateWeighed='2011-04-15' then personsWeight else 0 end) `04/15/2011`,
  sum(case when dateWeighed='2011-04-18' then personsWeight else 0 end) `04/18/2011`,
  sum(case when dateWeighed='2011-06-30' then personsWeight else 0 end) `06/30/2011`
from yt
group by personsId;

请参阅SQL Fiddle with Demo

但是如果你有一个未知数量的dates想要转换成列,那么你将需要使用预准备语句来生成动态SQL:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'sum(CASE WHEN dateWeighed = ''',
      dateWeighed,
      ''' THEN personsWeight else 0 END) AS `',
      date_format(dateWeighed, '%m/%d/%Y'), '`'
    )
  ) INTO @sql
FROM yt;

SET @sql 
  = CONCAT('SELECT personsId, ', @sql, ' 
            from yt
            group by personsId');

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

SQL Fiddle with Demo。两者都会给出结果:

| PERSONSID | 04/15/2011 | 04/18/2011 | 06/30/2011 | 07/11/2011 | 04/01/2012 |
------------------------------------------------------------------------------
|         1 |        160 |        161 |        162 |        163 |        164 |