使用动态SQL将列(不止一列)拆分为多列

时间:2019-01-23 08:19:24

标签: sql sql-server tsql pivot

我的数据表如下

enter image description here

我有将一列转换为多列的结果。但是我需要输出来转换多列

预期结果如下

输出为

Name    Q1      G1      Q2      G2     Q3        G3  
Antony  HSE      A     Degree   C      NULL      NULL
Bob     HSE      B     Degree   B      Masters   A
Marc    HSE      D     Degree   C      Masters   B

1 个答案:

答案 0 :(得分:2)

如果这些资格具有固定值,则可以通过条件汇总获得该结果。

SELECT
Name,
MAX(CASE WHEN Qualification = 'HSE' THEN Qualification END) AS Q1,
MAX(CASE WHEN Qualification = 'HSE' THEN Grade END) AS G1,
MAX(CASE WHEN Qualification = 'Degree' THEN Qualification END) AS Q2,
MAX(CASE WHEN Qualification = 'Degree' THEN Grade END) AS G2,
MAX(CASE WHEN Qualification = 'Masters' THEN Qualification END) AS Q3,
MAX(CASE WHEN Qualification = 'Masters' THEN Grade END) AS G3
FROM YourTable
GROUP BY Name
ORDER BY Name

如果资格名称不确定,则可以生成row_number并使用它。
然后,您可以添加尽可能多的Qn和Gn,就像一个Name可以具有限定一样。
要进行测试:select top 1 [Name], count(*) Total from @YourTable group by [Name] order by Total desc

SELECT 
Name,
MAX(CASE WHEN RN = 1 THEN Qualification END) AS Q1,
MAX(CASE WHEN RN = 1 THEN Grade END) AS G1,
MAX(CASE WHEN RN = 2 THEN Qualification END) AS Q2,
MAX(CASE WHEN RN = 2 THEN Grade END) AS G2,
MAX(CASE WHEN RN = 3 THEN Qualification END) AS Q3,
MAX(CASE WHEN RN = 3 THEN Grade END) AS G3
FROM 
( 
   SELECT Name, Qualification, Grade,
   ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Qualification) AS RN
   FROM YourTable
) q
GROUP BY Name
ORDER BY Name

或者动态地进行

declare @MaxTotalQualifications int = (select top 1 count(*) from YourTable group by [Name] order by count(*) desc);

declare @cols varchar(max);

WITH DIGITS(n) AS (
 SELECT n FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) v(n)
)
, NUMBERS(n) AS
(
SELECT ones.n + 10*tens.n + 100*hundreds.n + 1000*thousands.n
FROM DIGITS AS ones 
CROSS JOIN DIGITS as tens 
CROSS JOIN DIGITS as hundreds 
CROSS JOIN DIGITS as thousands
)
select @cols = concat(@cols+CHAR(13)+CHAR(10)+', ', 'MAX(CASE WHEN RN = ', n ,' THEN Qualification END) AS [Q', n ,'], MAX(CASE WHEN RN = ', n ,' THEN Grade END) AS [G', n,']')
from NUMBERS
WHERE n BETWEEN 1 AND @MaxTotalQualifications;

-- select @MaxTotalQualifications as MaxTotalQualifications, @cols as cols;

declare @DynSql nvarchar(max);

set @DynSql = N'SELECT Name, '+ @cols + N'
FROM 
( 
   SELECT Name, Qualification, Grade,
   ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Qualification) AS RN
   FROM YourTable
) q
GROUP BY Name
ORDER BY Name';

-- select @DynSql as DynSql;

exec(@DynSql);

db <>小提琴here

的测试