原文链接:https://www.cnblogs.com/kylan/p/10844414.html
本文使用的方法:
1、用Case When,个人推荐使用case when 的方法,比较灵活(原理是:使用group by 达到distinct 的效果,使多行变为1行)
2、PIVOT函数
-- 创建模拟数据 CREATE TABLE #TempSubjectResult(StudentName NVARCHAR(50) NOT NULL,StudentSubject NVARCHAR(50) NOT NULL,StudentGrade DECIMAL(4,1) NOT NULL) INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小姚','语文','80') INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小姚','数学','70') INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小姚','英语','60') INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小明','语文','90') INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小明','数学','95') INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小明','英语','98') SELECT * FROM #TempSubjectResult
表数据为:
-----------------------------------------------------------------------------普通版:转置的列确定-----------------------------------------------------------------------
方法一:Case When
-- 1 Case When普通版 SELECT StudentName 学生名, MAX(CASE WHEN StudentSubject='语文' THEN StudentGrade END) 语文, MAX(CASE WHEN StudentSubject='数学' THEN StudentGrade END) 数学, MAX(CASE WHEN StudentSubject='英语' THEN StudentGrade END) 英语 FROM #TempSubjectResult GROUP BY StudentName
方法二:PIVOT函数
SELECT * FROM #TempSubjectResult PIVOT(MAX(StudentGrade) FOR StudentSubject IN([语文],[数学],[英语])) T
-----------------------------------------------------------------------------升级版:转置的列不确定---------------------------------------------------------------------
方法三、 Case When升级版 动态SQL
-- Case When升级版 动态SQL DECLARE @SqlText NVARCHAR(4000)='SELECT StudentName ''学生名'', ' -- SQL头部分 SELECT SELECT @SqlText=@SqlText+' MAX(CASE WHEN StudentSubject='''+StudentSubject+''' THEN StudentGrade END) '''+StudentSubject +''',' FROM (SELECT DISTINCT StudentSubject FROM #TempSubjectResult) T -- 拼接CASE WHEN SELECT @SqlText= LEFT(@SqlText,LEN(@SqlText)-1)+' FROM #TempSubjectResult GROUP BY StudentName' -- 拼接 FROM后面部分 PRINT @SqlText EXEC (@SqlText)
方法四、PIVOT升级版 动态SQL
DECLARE @SqlSubject NVARCHAR(4000) SELECT @SqlSubject= STUFF((SELECT ','+'['+StudentSubject+']' FROM (SELECT DISTINCT StudentSubject FROM #TempSubjectResult) T FOR XML PATH('')),1,1,'') -- 获取PIVOT科目 DECLARE @SqlPIVOT NVARCHAR(4000)='SELECT * FROM #TempSubjectResult PIVOT(MAX(StudentGrade) FOR StudentSubject IN('+@SqlSubject+')) T' -- 拼接PIVOT PRINT @SqlPIVOT EXEC (@SqlPIVOT)
以下情况推荐使用动态转换:
1、需要转置的列不确定,比如转置月的天数,月份的天数有28.29.30.31天,不确定
2、需要转置的列非常多时候,不方便一个个写
附:完整代码
-- 创建模拟数据 CREATE TABLE #TempSubjectResult ( StudentName NVARCHAR(50) NOT NULL, StudentSubject NVARCHAR(50) NOT NULL, StudentGrade DECIMAL(4,1) NOT NULL ) INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小姚','语文','80') INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小姚','数学','70') INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小姚','英语','60') INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小明','语文','90') INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小明','数学','95') INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小明','英语','98') SELECT * FROM #TempSubjectResult -- 1 Case When普通版 SELECT StudentName 学生名, MAX(CASE WHEN StudentSubject='语文' THEN StudentGrade END) 语文, MAX(CASE WHEN StudentSubject='数学' THEN StudentGrade END) 数学, MAX(CASE WHEN StudentSubject='英语' THEN StudentGrade END) 英语 FROM #TempSubjectResult GROUP BY StudentName -- 2 PIVOT普通版 SELECT * FROM #TempSubjectResult PIVOT(MAX(StudentGrade) FOR StudentSubject IN([语文],[数学],[英语])) T -- 3 Case When升级版 动态SQL DECLARE @SqlText NVARCHAR(4000)='SELECT StudentName ''学生名'', ' -- SQL头部分 SELECT SELECT @SqlText=@SqlText+' MAX(CASE WHEN StudentSubject='''+StudentSubject+''' THEN StudentGrade END) '''+StudentSubject +''',' FROM (SELECT DISTINCT StudentSubject FROM #TempSubjectResult) T -- 拼接CASE WHEN SELECT @SqlText= LEFT(@SqlText,LEN(@SqlText)-1)+' FROM #TempSubjectResult GROUP BY StudentName' -- 拼接 FROM后面部分 PRINT @SqlText EXEC (@SqlText) -- 4 PIVOT升级版 动态SQL DECLARE @SqlSubject NVARCHAR(4000) SELECT @SqlSubject= STUFF((SELECT ','+'['+StudentSubject+']' FROM (SELECT DISTINCT StudentSubject FROM #TempSubjectResult) T FOR XML PATH('')),1,1,'') -- 获取PIVOT科目 DECLARE @SqlPIVOT NVARCHAR(4000)='SELECT * FROM #TempSubjectResult PIVOT(MAX(StudentGrade) FOR StudentSubject IN('+@SqlSubject+')) T' -- 拼接PIVOT PRINT @SqlPIVOT EXEC (@SqlPIVOT) DROP TABLE #TempSubjectResult
行转列的弊端是:如果某个值有多行,则只会出现根据聚合函数出现其中的一个值,其它值不体现
例: