SQL Server行转列、不确定列的行转列
本文使用的方法:
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行转列、不确定列的行转列的更多相关文章
- [转帖]SQL Server 索引中include的魅力(具有包含性列的索引)
SQL Server 索引中include的魅力(具有包含性列的索引) http://www.cnblogs.com/gaizai/archive/2010/01/11/1644358.html 上个 ...
- sql server 查询分析器消息栏里去掉“(5 行受影响)”
sql server 查询分析器消息栏里去掉"(5 行受影响)" 在你代码的开始部分加上这个命令: set nocount on 记住在代码结尾的地方再加上: set ...
- SQL Server 执行计划利用统计信息对数据行的预估原理二(为什么复合索引列顺序会影响到执行计划对数据行的预估)
本文出处:http://www.cnblogs.com/wy123/p/6008477.html 关于统计信息对数据行数做预估,之前写过对非相关列(单独或者单独的索引列)进行预估时候的算法,参考这里. ...
- sql server的for xml path与变通的行转列
SQL Server中有提供一个FOR XML PATH的子句(不知道能不能叫函数),用来将查询结果行输出成XML格式,我们可以通过这个语法做一些变通实现一些特定的功能,比如说行转列.要会变通的话,当 ...
- SQL Server 索引中include的魅力(具有包含性列的索引)
2010-01-11 20:44 by 听风吹雨, 22580 阅读, 24 评论, 收藏, 编辑 开文之前首先要讲讲几个概念 [覆盖查询] 当索引包含查询引用的所有列时,它通常称为“覆盖查询”. [ ...
- SQL Server 索引中include的魅力(具有包含性列的索引)(转载)
开文之前首先要讲讲几个概念 [覆盖查询] 当索引包含查询引用的所有列时,它通常称为“覆盖查询”. [索引覆盖] 如果返回的数据列就包含于索引的键值中,或者包含于索引的键值+聚集索引的键值中,那么就不 ...
- SQL Server 执行计划利用统计信息对数据行的预估原理以及SQL Server 2014中预估策略的改变
前提 本文仅讨论SQL Server查询时, 对于非复合统计信息,也即每个字段的统计信息只包含当前列的数据分布的情况下, 在用多个字段进行组合查询的时候,如何根据统计信息去预估行数的. 利用不同字段 ...
- SQL Server ->> 深入探讨SQL Server 2016新特性之 --- Row-Level Security(行级别安全控制)
SQL Server 2016 CPT3中包含了一个新特性叫Row Level Security(RLS),允许数据库管理员根据业务需要依据客户端执行脚本的一些特性控制客户端能够访问的数据行,比如,我 ...
- SQL Server 2008 R2中,“选择前1000行”为“选择所有行”
从SQL Server 2008开始,微软为了提高查询效率等原因,右键点击表时弹出菜单中默认没有"显示所有行",而以"选择前1000行"替代. 点击[工具]-& ...
- SQL Server 2008 R2不支持limit(限制行数)
SQL Server 2008 R2不支持limit 可用:select top 3 * from Websites2 MySQL 语法 SELECT *FROM PersonsLIMIT 5; Or ...
随机推荐
- Network Lock Manager Protocol (NLM)
资料来源 https://wiki.wireshark.org/Network_Lock_Manager 目的 The purpose of the NLM protocol is to provid ...
- 转 Oracle 同一个字段的两值进行加减计算
https://www.cnblogs.com/hjianguo/p/6041617.html 如 病人ID 入院日期 出院日期 00001 2016 ...
- (记录问题)1.Canvas.drawArc()方法的问题
先看看异常: 一眼看去就知道说的是方法找不到错误 后面发现是系统版本过低,4.0的系统找不到5.0后添加的方法报的错. 修改后完美解决
- 【Docker学习之二】Docker部署安装
环境 docker-ce-19.03.1-3.el7.x86_64 一.Docker的部署安装 Docker采用Linux(内核)技术,所以只能运行在Linux上,官方说Linux kernel至少3 ...
- kafka高可用性集群
kafka集群并测试其高可用性 介绍 Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写.Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站 ...
- nginx配置优化提高并发量
1 nginx配置优化提高并发量 worker_processes 2; 这个按照CPU的核数来决定 2 worker_connections 65535; 这个一般设置65535即可 每个进程允许的 ...
- vba实现工具的序列号验证框架
对于密码破译方面笔者不太懂,之前对于各种序列号的激活也有些臆测,自己根据想法做了个序列号验证的小框架,以后做的工具也可以用之保护一下下... 主要思路是:用户打开小工具后,系统检测是否已激活,如果未激 ...
- java 调用Spring接口上传文件及其他参数填充
第一步:在Spring配置中添加以下内容 <!-- 配置MultipartResolver 用于文件上传 使用spring的CommosMultipartResolver --> < ...
- flask源码系列
更新中 HTML文档中元素存在,但是在浏览器中不显示.一般用于配合JavaScript代码使用. 04 LocalStack和Local对象实现栈的管理 05 Flask源码之:配置加载 06 Fla ...
- python并发编程之IO模型 同步 异步 阻塞 非阻塞
IO浅谈 首先 我们在谈及IO模型的时候,就必须要引入一个“操作系统”级别的调度者-系统内核(kernel),而阻塞非阻塞是跟进程/线程严密相关的,而进程/线程又是依赖于操作系统存在的,所以自然不能脱 ...