本文使用的方法:

1、用Case When

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

以上为知道学科有“语文、数学、英语”,如果不确定科目呢?

此时可以用动态SQL查询,请看进阶版

-----------------------------------------------------------------------------升级版:转置的列不确定-----------------------------------------------------------------------------

方法三、 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 ('小姚','语文','')
INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小姚','数学','')
INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小姚','英语','')
INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小明','语文','')
INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小明','数学','')
INSERT INTO #TempSubjectResult(StudentName,StudentSubject,StudentGrade) VALUES ('小明','英语','') 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

SQL Server行转列、不确定列的行转列的更多相关文章

  1. [转帖]SQL Server 索引中include的魅力(具有包含性列的索引)

    SQL Server 索引中include的魅力(具有包含性列的索引) http://www.cnblogs.com/gaizai/archive/2010/01/11/1644358.html 上个 ...

  2. sql server 查询分析器消息栏里去掉“(5 行受影响)”

    sql server 查询分析器消息栏里去掉"(5 行受影响)"     在你代码的开始部分加上这个命令: set nocount on   记住在代码结尾的地方再加上: set ...

  3. SQL Server 执行计划利用统计信息对数据行的预估原理二(为什么复合索引列顺序会影响到执行计划对数据行的预估)

    本文出处:http://www.cnblogs.com/wy123/p/6008477.html 关于统计信息对数据行数做预估,之前写过对非相关列(单独或者单独的索引列)进行预估时候的算法,参考这里. ...

  4. sql server的for xml path与变通的行转列

    SQL Server中有提供一个FOR XML PATH的子句(不知道能不能叫函数),用来将查询结果行输出成XML格式,我们可以通过这个语法做一些变通实现一些特定的功能,比如说行转列.要会变通的话,当 ...

  5. SQL Server 索引中include的魅力(具有包含性列的索引)

    2010-01-11 20:44 by 听风吹雨, 22580 阅读, 24 评论, 收藏, 编辑 开文之前首先要讲讲几个概念 [覆盖查询] 当索引包含查询引用的所有列时,它通常称为“覆盖查询”. [ ...

  6. SQL Server 索引中include的魅力(具有包含性列的索引)(转载)

    开文之前首先要讲讲几个概念 [覆盖查询] 当索引包含查询引用的所有列时,它通常称为“覆盖查询”.  [索引覆盖] 如果返回的数据列就包含于索引的键值中,或者包含于索引的键值+聚集索引的键值中,那么就不 ...

  7. SQL Server 执行计划利用统计信息对数据行的预估原理以及SQL Server 2014中预估策略的改变

    前提  本文仅讨论SQL Server查询时, 对于非复合统计信息,也即每个字段的统计信息只包含当前列的数据分布的情况下, 在用多个字段进行组合查询的时候,如何根据统计信息去预估行数的. 利用不同字段 ...

  8. SQL Server ->> 深入探讨SQL Server 2016新特性之 --- Row-Level Security(行级别安全控制)

    SQL Server 2016 CPT3中包含了一个新特性叫Row Level Security(RLS),允许数据库管理员根据业务需要依据客户端执行脚本的一些特性控制客户端能够访问的数据行,比如,我 ...

  9. SQL Server 2008 R2中,“选择前1000行”为“选择所有行”

    从SQL Server 2008开始,微软为了提高查询效率等原因,右键点击表时弹出菜单中默认没有"显示所有行",而以"选择前1000行"替代. 点击[工具]-& ...

  10. SQL Server 2008 R2不支持limit(限制行数)

    SQL Server 2008 R2不支持limit 可用:select top 3 * from Websites2 MySQL 语法 SELECT *FROM PersonsLIMIT 5; Or ...

随机推荐

  1. 【GMT43智能液晶模块】例程二十:LAN_DNS实验——域名解析

    源代码下载链接: 链接:https://pan.baidu.com/s/16EW6AYpHpXljmBdNvMJM7g提取码:6lyk 复制这段内容后打开百度网盘手机App,操作更方便哦 GMT43购 ...

  2. osgb文件过大,可以通过Compressor=zlib对纹理进行压缩

    osg::ref_ptr<osgDB::ReaderWriter::Options> options = new osgDB::ReaderWriter::Options; options ...

  3. 解决Invalid Plugin needs a valid package.json

    首先.npm install -g plugman 然后,plugman   create    --name  [插件名字]    --plugin_id    [插件id] 这样会生成一个除了pa ...

  4. awk:for循环输出文件名

    简单来说,有file1.txt, file2.txt, file3.txt file1.txt如下: 1 a 4 d d g file2.txt如下: 2 b g 6 9 0 file3.txt如下: ...

  5. (CSDN 迁移) JAVA循环删除List的某个元素

    若列表中只可能存在一个则可以用简单的循环删除,不多说. 若列表中可能存在多个,尤其是可能有多个连续的需要删除,用简单循环有可能发生异常. 需要使用迭代器(Iterator),两种具体实现: 逻辑上是一 ...

  6. Java操作fastDFS

    一.加入Maven依赖 <dependency> <groupId>org.csource</groupId> <artifactId>fastdfs- ...

  7. Codeforces Round #603 (Div. 2) (题解)

    A. Sweet Problem (找规律) 题目链接 大致思路: 有一点瞎猜的,首先排一个序, \(a_1>a_2>a_3\) ,发现如果 \(a_1>=a_2+a_3\) ,那么 ...

  8. 找出二进制数中bit为1的最(高/低)索引

    题1.  给定一个无符号整型数据(unsigned int),找出其对应二进制数据中bit位为1的最高/低索引. 比如:对于数据0,返回0:数据1,返回1:数据0x80000000,返回32: 题2. ...

  9. pytest_06_fixture之yield实现teardown

    上一篇讲到fixture通过scope参数控制setup级别,既然有setup作为用例之前前的操作,用例执行完之后那肯定也有teardown操作. 这里用到fixture的teardown操作并不是独 ...

  10. MNIST机器学习入门(二)

    在前一个博客中,我们已经对MNIST 数据集和TensorFlow 中MNIST 数据集的载入有了基本的了解.本节将真正以TensorFlow 为工具,写一个手写体数字识别程序,使用的机器学习方法是S ...