老生常谈之SQL Server (行转列,列转行)
Open the first article

在本文章中主要介绍以下内容:
- 1、静态行转列
- 2、静态列转行
- 3、动态行转列
- 4、动态列转行
1、静态行转列
--静态的行转列
--新建一个科目成绩表
--三个字段:学生名称,科目,成绩
CREATE TABLE SubjectScore
(
StuName nvarchar(20),
SubjectName nvarchar(20),
Fraction decimal(16,2)
) --插入4条数据
INSERT INTO SubjectScore
VALUES(N'孔子',N'语文',99) INSERT INTO SubjectScore
VALUES(N'孔子',N'数学',80) INSERT INTO SubjectScore
VALUES(N'诸葛',N'语文',75.5) INSERT INTO SubjectScore
VALUES(N'诸葛',N'数学',66) --行转列
SELECT StuName,
ISNULL(SUM(case SubjectName when N'语文' then isnull(Fraction,0)end),0)as N'语文',
ISNULL(SUM(case SubjectName when N'数学' then isnull(Fraction,0)end),0)as N'数学'
FROM SubjectScore
GROUP BY StuName --如果加了个英语科目怎么办?没错,代码要改
--下面我们加个英文科目
INSERT INTO SubjectScore
VALUES(N'诸葛',N'英语',66) --修改代码后行转列
SELECT StuName,
ISNULL(SUM(case SubjectName when N'语文' then isnull(Fraction,0)end),0)as N'语文',
ISNULL(SUM(case SubjectName when N'数学' then isnull(Fraction,0)end),0)as N'数学',
ISNULL(SUM(case SubjectName when N'英语' then isnull(Fraction,0)end),0)as N'英语'
FROM SubjectScore
GROUP BY StuName
结果:

2、静态列转行
--静态列转行
--表结构:我们建几个中文的字段:学生名称,语文,数学
CREATE TABLE Demo_Stu
(
学生名称 nvarchar(20),
语文 decimal(16,2),
数学 decimal(16,2)
) --一样插入4条数据
INSERT INTO Demo_Stu
VALUES(N'孔子',88,99) INSERT INTO Demo_Stu
VALUES(N'孔子',99,69) INSERT INTO Demo_Stu
VALUES(N'诸葛',88,55) INSERT INTO Demo_Stu
VALUES(N'诸葛',77,63) --我们可以用union all 来实现,
--不了解 union all怎么用的兄弟请自行百度
select * from (
select 学生名称 as StuName,Subject=N'语文',Fraction=语文 from Demo_Stu
union all
select 学生名称 as StuName,Subject=N'数学',Fraction=数学 from Demo_Stu
)p order by StuName
结果:

3、动态行转列
--动态的行转列
--科目成绩表
--三个字段:学生名称,科目,成绩
CREATE TABLE SubjectScore
(
StuName nvarchar(20),
SubjectName nvarchar(20),
Fraction decimal(16,2)
) --插入4条数据
INSERT INTO SubjectScore
VALUES(N'孔子',N'语文',99) INSERT INTO SubjectScore
VALUES(N'孔子',N'数学',80) INSERT INTO SubjectScore
VALUES(N'诸葛',N'语文',75.5) INSERT INTO SubjectScore
VALUES(N'诸葛',N'数学',66) /*
动态行转列我们主要用到以下几个关键函数:
2.PIVOT
1.QUOTENAME
*/
DECLARE @sql_col NVARCHAR(4000)
DECLARE @sql_str NVARCHAR(4000)
/*取表中行转列的所有科目*/
SELECT @sql_col = ISNULL(@sql_col+',','')+QUOTENAME(SubjectName) FROM SubjectScore GROUP BY SubjectName
SET @sql_str = '
SELECT * FROM SubjectScore p PIVOT(
SUM([Fraction]) FOR [SubjectName] IN('+@sql_col+')
) pvt
order by StuName
'
EXEC (@sql_str) --如果加了个英语科目怎么办?代码不需要改动
--下面我们加个历史科目,再执行上面的行转列代码
INSERT INTO SubjectScore
VALUES(N'诸葛',N'历史',88) INSERT INTO SubjectScore
VALUES(N'孔子',N'历史',99)
结果:

4、动态列转行
--动态态列转行
--表结构:我们建几个中文的字段:学生名称,语文,数学
CREATE TABLE Demo_Stu
(
学生名称 nvarchar(20),
语文 decimal(16,2),
数学 decimal(16,2)
) --一样插入4条数据
INSERT INTO Demo_Stu
VALUES(N'孔子',88,99) INSERT INTO Demo_Stu
VALUES(N'孔子',99,69) INSERT INTO Demo_Stu
VALUES(N'诸葛',88,55) INSERT INTO Demo_Stu
VALUES(N'诸葛',77,63) --列传行
--列转行的方案来源于:Joe.TJ
--列转行的动态方案:UNPIVOT,sql2005及以后版本
--因为行是动态所以这里就从INFORMATION_SCHEMA.COLUMNS视图中获取列来构造行,同样也使用了XML处理。
DECLARE @SQL NVARCHAR(4000)=N'';
SET @SQL=STUFF((SELECT N','+QUOTENAME(COLUMN_NAME ) FROM INFORMATION_SCHEMA.COLUMNS
WHERE ORDINAL_POSITION>1 AND TABLE_NAME='Demo_Stu' FOR XML PATH('')),1,1,N'')
SET @SQL=N'SELECT *
from dbo.Demo_Stu
unpivot(分数 for 科目 in('+@SQL+'))as up';
EXEC SP_EXECUTESQL @SQL;
总结:
无论是静态的行转列或列转行都是会增加代码的维护性。
建议使用动态的行转列和列转行,可减少代码的维护性,多留一手也是比较好的。
老生常谈之SQL Server (行转列,列转行)的更多相关文章
- SQL Server自动化运维系列——关于邮件通知那点事(.Net开发人员的福利)
需求描述 在我们的生产环境中,大部分情况下需要有自己的运维体制,包括自己健康状态的检测等.如果发生异常,需要提前预警的,通知形式一般为发邮件告知. 邮件作为一种非常便利的预警实现方式,在及时性和易用性 ...
- SQL Server中的标识列
一.标识列的定义以及特点 SQL Server中的标识列又称标识符列,习惯上又叫自增列. 该种列具有以下三种特点: .列的数据类型为不带小数的数值类型 .在进行插入(Insert)操作时,该列的值是由 ...
- SQL Server 2016:内存列存储索引
作者 Jonathan Allen,译者 谢丽 SQL Server 2016的一项新特性是可以在“内存优化表(Memory Optimized Table)”上添加“列存储索引(Columnstor ...
- SQL Server ->> ColumnStore Index(列存储索引)
Columnstored index是SQL Server 2012后加入的重大特性,数据不再以heap或者B Tree的形式存储(row level)存储在每一个数据库文件的页里面,而是以列为单位存 ...
- Sql Server中的标识列(自增长字段)
一.标识列的定义以及特点 SQL Server中的标识列又称标识符列,习惯上又叫自增列.该种列具有以下三种特点: 1.列的数据类型为不带小数的数值类型2.在进行插入(Insert)操作时,该列的值是由 ...
- SQL Server自动化运维系列——监控跑批Job运行状态(Power Shell)
需求描述 在我们的生产环境中,大部分情况下需要有自己的运维体制,包括自己健康状态的检测等.如果发生异常,需要提前预警的,通知形式一般为发邮件告知. 在上一篇文章中已经分析了SQL SERVER中关于邮 ...
- SQL SERVER将某一列字段中的某个值替换为其他的值 分类: MSSQL 2014-11-05 13:11 67人阅读 评论(0) 收藏
SQL SERVER将某一列字段中的某个值替换为其他的值 UPDATE 表名 SET 列名 = REPLACE(列名 ,'贷','袋') SQL SERVER"函数 replace 的参数 ...
- SQL Server 行转列重温
转载自http://www.cnblogs.com/kerrycode/ 行转列,列转行是我们在开发过程中经常碰到的问题.行转列一般通过CASE WHEN 语句来实现,也可以通过 SQL SERVER ...
- 【转载】SQL Server行转列,列转行
行转列,列转行是我们在开发过程中经常碰到的问题.行转列一般通过CASE WHEN 语句来实现,也可以通过 SQL SERVER 2005 新增的运算符PIVOT来实现.用传统的方法,比较好理解.层次清 ...
- Sql Server 行转列
--摘自百度 PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PIVOT(聚合函数(列) FOR 列 in (… ...
随机推荐
- 第4章 ext文件系统机制
本文目录: 4.1 文件系统的组成部分 4.2 文件系统的完整结构 4.3 Data Block 4.4 inode基础知识 4.5 inode深入 4.6 单文件系统中文件操作的原理 4.7 多文件 ...
- gawk的用法
GNU gawk工具的功能是将指定文件中符合指定模式(pattern)的行按指定的动作(action)进行格式化处理 语法:gawk [options] [program] [file-lis ...
- AngularJS高级程序设计读书笔记 -- 大纲篇
零. 初衷 现在 AngularJS 4 已经发布了, 楼主还停留在 1.x 的阶段, 深感自卑. 学习 AngularJS 的初衷是因为, 去年楼主开始尝试使用 Flask 开发自动化程序, 需要用 ...
- ASP.NET Core部署到CentOS7,使用Nginx代理
ASP.NET Core 的运行环境由新开发的 Kestrel Server 负责,IIS 退回到 HTTP 的侦听器的角色,微软也特别为了这个需求开发了 IIS Platform Handler,以 ...
- Sqlserver 2005 跨数据库 导入数据
--Sqlserver 2005 跨数据库 导入数据:--SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEMENT'OpenRowset/O ...
- 如何退出 Vim
点击 Esc 键,; Vim 进入命令模式.然后输入: :q 退出(这是 :quit 的缩写) :q! 不保存退出(这是 :quit! 的缩写) :wq 写入文件并退出:(这是 :writequi ...
- laydate时间插件更换皮肤
<script> ;!function(){ laydate.skin('molv'); laydate({ elem: '#demo' }) }();</script>
- [leetcode-532-K-diff Pairs in an Array]
Given an array of integers and an integer k, you need to find the number of unique k-diff pairs in t ...
- 10.application对象
1.application对象实现了用户数据的共享,可存放全局变量 2.application开始于服务器的启动,终止于服务器的关闭. 3.在用户的前后连接或不同用户之间的连接中,可以对applica ...
- RandomAccessFile乱码问题
转自:http://www.cnblogs.com/xudong-bupt/archive/2013/04/20/3028980.html Thanks Java对文件的读.写随机访问,Ran ...