SQL Transpose Rows到未定义的列数

时间:2015-05-19 09:06:17

标签: sql sql-server pivot transpose

我有一张包含研究生ID,学位和毕业年份的表格。该表可以包含每个毕业生的任意数量的行。

Current Table structure

我想创建一个视图,将所有行转换为所需数量的列,并在没有数据的列中输入“null”。

Desired output

我在这里已经看过很多次这个问题,但我担心他们要么没有被标记为已回答,要么我不理解解决方案。所以我再次提出这个问题,希望使用我的表结构,我会更好地理解解决方案。

非常感谢任何帮助。

修改 这不一定是视图

1 个答案:

答案 0 :(得分:2)

answer中详细描述了执行此操作的一般方法,但是当您希望按特定顺序(degree1,year1,degree2,year2,等...)可能有点棘手。

这是一种方法,我相信如果您查看我上面链接的答案,代码是不言自明的,我将不再进一步解释:

DECLARE @sql AS NVARCHAR(MAX)
DECLARE @title_cols AS NVARCHAR(MAX)
DECLARE @year_cols AS NVARCHAR(MAX)
DECLARE @header AS NVARCHAR(MAX)

SELECT 
    @title_cols = ISNULL(@title_cols + ',','') + QUOTENAME(rn),
    @year_cols  = ISNULL(@year_cols + ',','') + QUOTENAME(CONCAT('y',rn)),
    @header = ISNULL(@header + ',','') + CONCAT('MAX(',QUOTENAME(rn) ,') AS "Degree Title ', rn, '", MAX(',QUOTENAME(CONCAT('y',rn)) ,') AS "Graduation Year ', rn, '"')
FROM (
  SELECT DISTINCT 
    rn = ROW_NUMBER() OVER (PARTITION BY [Graduate ID] ORDER BY [Degree Title], [Graduation Year]) 
  FROM Graduates
) GRADS

SET @sql =
  N'SELECT [Graduate ID], ' + @header + '
    FROM (
       SELECT *,
          title = ROW_NUMBER() OVER (PARTITION BY [Graduate ID] ORDER BY [Graduation Year]),
          year = CONCAT(''y'',ROW_NUMBER() OVER (PARTITION BY [Graduate ID] ORDER BY [Graduation Year])) 
       FROM Graduates) g
    PIVOT(MAX([Degree Title]) FOR title IN (' + @title_cols + ')) AS Titles
    PIVOT(MAX([Graduation Year]) FOR year IN (' + @year_cols + ')) AS Years
    GROUP BY [Graduate ID]'

EXEC sp_executesql @sql

Sample SQL Fiddle

该查询使用SQL Server 2012及更高版本中提供的concat()函数,因此如果您使用的是旧版本,则必须将该部分更改为使用强制转换的“正常”字符串连接。

我确信可以通过多种方式改进查询,但我会将其作为练习:)