转换列中的行

时间:2013-01-10 11:49:24

标签: sql database sql-server-2008 pivot

我有这张桌子:

idSection   | idQuestion    | title     | enunciation | total   | name 
1           | 1             | title 1   | question 1    | 5     | Good
1           | 1             | title 1   | question 1    | 3     | Very Good
1           | 1             | title 1   | question 1    | 1     | Bad
1           | 2             | title 2   | question 2    | 1     | Good
1           | 2             | title 2   | question 2    | 3     | Bad
1           | 3             | title 3   | question 3    | 1     | Bad

如何在多列中创建列值名称

以下是预期结果:

title   | enunciantion  | bad   | good  | very good 
title 1 | question 1    | 1     | 5     | 3
title 2 | question 2    | 3     | 1     | 0
title 3 | question 3    | 1     | 0     | 0

我不知道会有多少列(它是动态的)。

新编辑:

 title      |  enunciantion | Column0  | Column1 | Column2 | ... | Column7 |
   0        |   0           | bad      |  good   |very good| ... |    0    |
title 1     | question 1    | 1        | 5       | 3       | ... |    0    |
title 2     | question 2    | 3        | 1       | 0       | ... |    0    |
title 3     | question 3    | 1        | 0       | 0       | ... |    5    |

现在,唯一的区别是,不是拥有动态列,而是只有静态列,但是表的第一行是这样的动态值,范围是另一个表。

2 个答案:

答案 0 :(得分:3)

对于MySQL:

SELECT
  title,
  enunciantion,
  SUM(CASE WHEN name = 'bad' THEN total ELSE 0 END) AS 'bad',
  SUM(CASE WHEN name = 'good' THEN total ELSE 0 END) AS 'good',
  SUM(CASE WHEN name = 'very good ' THEN total ELSE 0 END) AS 'very good'
FROM Tablename
GROUP BY  title,
          enunciantion;

SQL Fiddle Demo

对于SQL Server:

SELECT
  title,
  enunciation,
  bad,
  good,
  [very good]
FROM Table1
PIVOT
(
  SUM(total) FOR name IN([good], [bad], [very good])
) p;

SQL Fiddle DemoSQL Server


更新

如果这些值good, bad, very good来自另一个表,并且您想要动态执行此操作。

对于MySQL:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT CONCAT('SUM(IF(Name = ''',
      Name, ''', Total, 0)) AS ',
      '''',Name, '''')
  ) INTO @sql
FROM names;


SET @sql = CONCAT('SELECT title, enunciation, ',
                  @sql,
                  'FROM Table1 GROUP BY  title, '
                  '  enunciation; ');
prepare stmt 
FROM @sql;

execute stmt;

SQL Fiddle DemoMySQL, dynamic

|   TITLE | ENUNCIATION | GOOD | VERY GOOD | BAD | VERY BAD |
-------------------------------------------------------------
| title 1 |  question 1 |    5 |         3 |   1 |        0 |
| title 2 |  question 2 |    1 |         0 |   3 |        0 |
| title 3 |  question 3 |    0 |         0 |   1 |        0 |

对于SQL Server,您可以这样做:

DECLARE @cols AS NVARCHAR(MAX);
DECLARE @query AS NVARCHAR(MAX);

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.name) 
                    from names c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

SET @query = 'SELECT  title, enunciation, ' + @cols +
              ' FROM (SELECT title, enunciation, total, name
      FROM Table1) t
PIVOT
(
  SUM(total) FOR name IN( ' + @cols + + ' )) p;';

execute(@query);

SQL Fiddle DemoSQL Server, dynamic

这会给你:

|   TITLE | ENUNCIATION | BAD |   GOOD | VERY BAD | VERY GOOD |
---------------------------------------------------------------
| title 1 |  question 1 |   1 |      5 |   (null) |         3 |
| title 2 |  question 2 |   3 |      1 |   (null) |    (null) |
| title 3 |  question 3 |   1 | (null) |   (null) |    (null) |

答案 1 :(得分:3)

仅针对SQL Server的动态SQL版本扩展@Mahmoud Gamal's答案。如果要将null值替换为零,则可以使用以下内容:

DECLARE @colsPivot AS NVARCHAR(MAX),
    @colsNull AS NVARCHAR(MAX),
    @query AS NVARCHAR(MAX);

select @colsPivot = STUFF((SELECT distinct ',' + QUOTENAME(c.name) 
                    from names c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

select @colsNull 
    = STUFF((SELECT distinct ', IsNull(' + QUOTENAME(c.name) + ', 0) as '+ QUOTENAME(c.name)
             from names c
             FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

SET @query = 'SELECT  title, enunciation, ' + @colsNull +
             ' FROM 
              (
                SELECT title, enunciation, total, name
                FROM results
              ) t
              PIVOT
              (
                  SUM(total) 
                  FOR name IN( ' + @colsPivot + + ' )
              ) p;';

exec(@query);

请参阅SQL Fiddle with Demo

结果是:

|   TITLE | ENUNCIATION | BAD | GOOD | VERY BAD | VERY GOOD |
-------------------------------------------------------------
| title 1 |  question 1 |   1 |    5 |        0 |         3 |
| title 2 |  question 2 |   3 |    1 |        0 |         0 |
| title 3 |  question 3 |   1 |    0 |        0 |         0 |