SQL 将行转置为未定义的列数
SQL Transpose Rows to undefined number of columns
我有一个 table,其中包含毕业生 ID、学位名称和毕业年份。 table 可以包含每个毕业生的任意行数。
我想创建一个视图,根据需要将所有行转换为尽可能多的列,并在没有数据的列中输入 'null'。
我已经看到这个问题在这里被问过好几次了,但恐怕他们要么没有被标记为已回答,要么我不明白解决方案。所以我再次问了这个问题,希望使用我的 table 结构我能更好地理解解决方案。
非常感谢您一如既往的帮助。
编辑:
这不一定是视图
此 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
该查询使用 concat()
函数,该函数在 SQL Server 2012 及更高版本中可用,因此如果您使用的是旧版本,则必须将该部分更改为 "normal" 带转换的字符串连接。
我确信查询可以在很多方面得到改进,但我会把它留作练习 :)
以ug为
(select * 来自学位名称如“B%”的毕业生)
以 pg 作为
(select * 来自学位名称如“M%”的毕业生)
以 pg1 作为
(select * 来自学位名称如“P%”的毕业生)
select
ug.id 作为毕业生 ID
, ug.Degree Title as Degree Title 1
,呃。毕业年作为毕业年 1
, pg1.Degree Title as Degree Title 2
, 第 1 页。毕业年作为毕业年 2
, pg2.Degree Title as Degree Title 3
, 第 2 页。毕业年作为毕业年 3
来自 ug
左加入 pg1
关于 ug.Graduate ID= pg1.Graduate ID
左加入pg2
关于 ug.Graduate ID= pg2.Graduate ID
我有一个 table,其中包含毕业生 ID、学位名称和毕业年份。 table 可以包含每个毕业生的任意行数。
我想创建一个视图,根据需要将所有行转换为尽可能多的列,并在没有数据的列中输入 'null'。
我已经看到这个问题在这里被问过好几次了,但恐怕他们要么没有被标记为已回答,要么我不明白解决方案。所以我再次问了这个问题,希望使用我的 table 结构我能更好地理解解决方案。
非常感谢您一如既往的帮助。
编辑: 这不一定是视图
此 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
该查询使用 concat()
函数,该函数在 SQL Server 2012 及更高版本中可用,因此如果您使用的是旧版本,则必须将该部分更改为 "normal" 带转换的字符串连接。
我确信查询可以在很多方面得到改进,但我会把它留作练习 :)
以ug为 (select * 来自学位名称如“B%”的毕业生) 以 pg 作为 (select * 来自学位名称如“M%”的毕业生) 以 pg1 作为 (select * 来自学位名称如“P%”的毕业生)
select ug.id 作为毕业生 ID , ug.Degree Title as Degree Title 1 ,呃。毕业年作为毕业年 1 , pg1.Degree Title as Degree Title 2 , 第 1 页。毕业年作为毕业年 2 , pg2.Degree Title as Degree Title 3 , 第 2 页。毕业年作为毕业年 3 来自 ug 左加入 pg1 关于 ug.Graduate ID= pg1.Graduate ID 左加入pg2 关于 ug.Graduate ID= pg2.Graduate ID