我有一个包含毕业生 ID、学位名称和毕业年份的表格。该表可以包含每个毕业生的任意数量的行。
我想创建一个 View ,将所有行转置为所需数量的列,并在没有数据的列中输入“null”。
我在这里多次看到这个问题,但恐怕他们要么没有被标记为已回答,要么我不明白解决方案。所以我再次问了这个问题,希望使用我的表结构我能更好地理解解决方案。
非常感谢一如既往的任何帮助。
编辑: 这不一定是 View
最佳答案
此 answer 中详细描述了执行此操作的通用方法。 ,但是当您希望列按特定顺序(学位 1、年份 1、学位 2、年份 2 等...)时,以动态方式将其应用于多个列可能会有点棘手。
这是实现此目的的一种方法,因为我相信如果您已经查看了我上面链接的答案,则代码是非常不言自明的,我不会进一步解释它:
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
查询使用 SQL Server 2012 及更高版本中提供的 concat()
函数,因此如果您使用的是旧版本,则必须将该部分更改为“正常”字符串连接与类型转换。
我确信查询可以在很多方面得到改进,但我将把它作为练习:)
关于SQL 将行转置为未定义数量的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30321217/