SQL Server 2008 R2——PIVOT 行转列 以及聚合函数的选择

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: 原文:SQL Server 2008 R2——PIVOT 行转列 以及聚合函数的选择==================================声明================================== 本文原创,转载在正文中显要的注明作者和出处,并保证文章的完整性。
原文: SQL Server 2008 R2——PIVOT 行转列 以及聚合函数的选择

==================================声明==================================

本文原创,转载在正文中显要的注明作者和出处,并保证文章的完整性。

未经作者同意请勿修改(包括本声明),保留法律追究的权利。

未经作者同意请勿用于学术性引用。

未经作者同意请勿用于商业出版、商业印刷、商业引用。

本文不定期修正完善,为保证内容正确,建议移步原文处阅读。

本文链接:http://www.cnblogs.com/wlsandwho/p/4423956.html

=======================================================================

看了好长时间的资料,总算是看懂了点。(另外怎样才能把右面的这个长毛的土豆去掉?---->                         对,就是它!)

赶紧记录下来。

=======================================================================

表格和数据。(和http://www.cnblogs.com/wlsandwho/p/4416222.html的相同)

 1 USE tempdb
 2 GO
 3 --------------------------------------------------------------------------
 4 IF OBJECT_ID('Student','U') IS NOT NULL
 5 DROP TABLE Student
 6 GO
 7 
 8 CREATE TABLE Student
 9 (
10     StuID NVARCHAR(8) PRIMARY KEY,
11     Name NVARCHAR(5),
12     EntranceTime DATETIME
13 )
14 GO
15 
16 INSERT INTO Student(StuID,Name,EntranceTime) VALUES('20080001','Lily','2008-08-27')
17 INSERT INTO Student(StuID,Name,EntranceTime) VALUES('20090002','Lucy','2009-08-26')
18 INSERT INTO Student(StuID,Name,EntranceTime) VALUES('20070003','Jack','2007-08-28')
19 GO
20 --------------------------------------------------------------------------
21 IF OBJECT_ID('SltCourse','U') IS NOT NULL
22 DROP TABLE SltCourse
23 GO
24 
25 CREATE TABLE SltCourse    --SelectiveCourse
26 (
27     ID INT PRIMARY KEY IDENTITY(1,1),
28     StuID NVARCHAR(8),
29     CourseName NVARCHAR(10),
30     Score    INT 
31 )
32 GO
33 
34 INSERT INTO SltCourse(StuID,CourseName,Score) VALUES('20070003','电脑维修',90)
35 INSERT INTO SltCourse(StuID,CourseName,Score) VALUES('20070003','剪纸',80)
36 INSERT INTO SltCourse(StuID,CourseName,Score) VALUES('20070003','市场策划',95)
37 INSERT INTO SltCourse(StuID,CourseName,Score) VALUES('20070003','信息检索',100)
38 
39 INSERT INTO SltCourse(StuID,CourseName,Score) VALUES('20080001','插花',99)
40 INSERT INTO SltCourse(StuID,CourseName,Score) VALUES('20080001','剪纸',96)
41 INSERT INTO SltCourse(StuID,CourseName,Score) VALUES('20080001','刺绣',92)
42 
43 INSERT INTO SltCourse(StuID,CourseName,Score) VALUES('20090002','插花',98)
44 GO

查看一下

1 SELECT s.StuID,s.Name,s.EntranceTime,sc.CourseName,sc.Score FROM Student s,SltCourse sc WHERE s.stuid=sc.stuid
2 GO

=======================================================================

现在来看这个表格,前三列有很多数据是重复的,而且也不便于阅读。之前使用了row_number函数,这里使用下别的——PIVOT来实现一个行转列。

预期效果。

=======================================================================

静态版。这需要预知要转换成列名的数据。

1 WITH ReportCard 
2 AS(
3 SELECT s.StuID,s.Name,s.EntranceTime,sc.CourseName,sc.Score FROM Student s,SltCourse sc WHERE s.stuid=sc.stuid
4 )
5 SELECT * FROM ReportCard PIVOT(MAX(Score) FOR CourseName IN([电脑维修],[剪纸],[市场策划],[信息检索],[插花],[刺绣]) ) AS T
6 GO

结果。

当在第三行加上筛选语句时,可以得到指定的某一行。例如:

1 WITH ReportCard 
2 AS(
3 SELECT s.StuID,s.Name,s.EntranceTime,sc.CourseName,sc.Score FROM Student s,SltCourse sc WHERE s.stuid=sc.stuid AND s.StuID='20090002'
4 )
5 SELECT * FROM ReportCard PIVOT(MAX(Score) FOR CourseName IN([电脑维修],[剪纸],[市场策划],[信息检索],[插花],[刺绣]) ) AS T
6 GO

结果。

=======================================================================

动态版。先查询出要转为列的行数据,然后设置格式,再拼接字符串。

 1 DECLARE @strCN NVARCHAR(100)
 2 SELECT @strCN=ISNULL(@strCN+',','')+ QUOTENAME(CourseName) FROM  SltCourse GROUP BY CourseName
 3 --PRINT @DCN
 4 
 5 DECLARE @SqlStr NVARCHAR(1000)
 6 SET @SqlStr='
 7 WITH ReportCard 
 8 AS(
 9 SELECT s.StuID,s.Name,s.EntranceTime,sc.CourseName,sc.Score FROM Student s,SltCourse sc WHERE s.stuid=sc.stuid 
10 )
11 SELECT * FROM ReportCard PIVOT(MAX(Score) FOR CourseName IN('+@strCN+') ) AS T'
12 EXEC(@sqlstr)
13 GO

=======================================================================

题外话,关于PIVOT中聚合函数的使用。

 

我刚用TSQL不久,行转列都是汇总一些数值类型的数据,比方说,周一到周日的营业收入啦,数理化史地生成绩啦之类的。

这些数值类型的,选择聚合函数时,当然是需要什么选什么啦。

看例子。

 1 USE tempdb
 2 GO
 3 
 4 IF OBJECT_ID('AggregateFuncTest1','U') IS NOT NULL
 5 DROP TABLE AggregateFuncTest1
 6 GO
 7 
 8 CREATE TABLE AggregateFuncTest1
 9 (
10     ID INT IDENTITY(1,1) PRIMARY KEY,
11     DayOfWeek NVARCHAR(3),
12     Income INT
13 )
14 GO
15 
16 INSERT INTO AggregateFuncTest1(DayOfWeek,Income) VALUES('星期一',100)
17 INSERT INTO AggregateFuncTest1(DayOfWeek,Income) VALUES('星期二',200)
18 INSERT INTO AggregateFuncTest1(DayOfWeek,Income) VALUES('星期三',300)
19 INSERT INTO AggregateFuncTest1(DayOfWeek,Income) VALUES('星期四',400)
20 INSERT INTO AggregateFuncTest1(DayOfWeek,Income) VALUES('星期五',500)
21 INSERT INTO AggregateFuncTest1(DayOfWeek,Income) VALUES('星期六',600)
22 INSERT INTO AggregateFuncTest1(DayOfWeek,Income) VALUES('星期日',700)
23 GO
24 ----------------------------------------------------------------------
25 SELECT DayOfWeek,Income FROM AggregateFuncTest1
26 GO
27 ----------------------------------------------------------------------
28 WITH Rst AS
29 (
30     SELECT DayOfWeek,Income FROM AggregateFuncTest1
31 )
32 SELECT [星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日] FROM Rst 
33 PIVOT(AVG(Income) FOR DayOfWeek IN ([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日])) AS T
34 GO
35 ----------------------------------------------------------------------
36 INSERT INTO AggregateFuncTest1(DayOfWeek,Income) VALUES('星期一',1000)
37 GO
38 
39 WITH Rst AS
40 (
41     SELECT DayOfWeek,Income FROM AggregateFuncTest1
42 )
43 SELECT [星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日] FROM Rst 
44 PIVOT(AVG(Income) FOR DayOfWeek IN ([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日])) AS T
45 GO
46 ----------------------------------------------------------------------
47 DROP TABLE AggregateFuncTest1

结果:

只要看一看、运行一下就会发现,聚合函数的选择是根据需要来的。当我有2个星期一的入账时,由AVG函数的来的结果是不同的。

那么,求最大就是用Max,最小用Min,求和就是Sum,等等等等。没啥说的。

如果数据是字符类型呢?

再看例子。例如,办公室值日表。

 1 USE tempdb
 2 GO
 3 
 4 IF OBJECT_ID('AggregateFuncTest2','U') IS NOT NULL
 5 DROP TABLE AggregateFuncTest2
 6 GO
 7 
 8 CREATE TABLE AggregateFuncTest2
 9 (
10     ID INT IDENTITY(1,1) PRIMARY KEY,
11     DayOfWeek NVARCHAR(3),
12     Name NVARCHAR(10)
13 )
14 GO
15 
16 INSERT INTO AggregateFuncTest2(DayOfWeek,Name) VALUES('星期一','Jack')
17 INSERT INTO AggregateFuncTest2(DayOfWeek,Name) VALUES('星期二','Lucy')
18 INSERT INTO AggregateFuncTest2(DayOfWeek,Name) VALUES('星期三','Lily')
19 INSERT INTO AggregateFuncTest2(DayOfWeek,Name) VALUES('星期四','Bob')
20 INSERT INTO AggregateFuncTest2(DayOfWeek,Name) VALUES('星期五','Angela')
21 INSERT INTO AggregateFuncTest2(DayOfWeek,Name) VALUES('星期六','Bella')
22 INSERT INTO AggregateFuncTest2(DayOfWeek,Name) VALUES('星期日','')
23 GO
24 ------------------------------------------------------------------------
25 SELECT DayOfWeek,Name FROM AggregateFuncTest2
26 GO
27 
28 WITH Rst AS
29 (SELECT DayOfWeek,Name FROM AggregateFuncTest2)
30 SELECT * FROM Rst PIVOT (MAX(Name) FOR DayOfWeek IN ([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日]) ) AS PVT
31 ------------------------------------------------------------------------
32 DROP TABLE AggregateFuncTest2

结果:

单个的数据可以用Max等函数来凑合使用,因为这些函数可以接受字符类型的参数。

但如果数据多了,不止一个的时候呢?例如,又来了一个同事,于是周六多了一个人,那就顺便大扫除吧。

1 INSERT INTO AggregateFuncTest2(DayOfWeek,Name) VALUES('星期六','Alice')
2 GO
3 WITH Rst AS
4 (SELECT DayOfWeek,Name FROM AggregateFuncTest2)
5 SELECT * FROM Rst PIVOT (MAX(Name) FOR DayOfWeek IN ([星期一],[星期二],[星期三],[星期四],[星期五],[星期六],[星期日]) ) AS PVT
6 GO

结果:

Alice居然不用值日,这怎么行!怎能不给表现的机会?女汉子能顶一个天!

这种情况只能自己专门写一个聚合函数来拼接字符串了。(当然可以先拼接好字符串,再行转列。)

=======================================================================

用户自定义聚合函数好复杂,不写了。(其实是我还没搞懂这些呢,C#无爱。)

 

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
5月前
|
SQL 存储 数据库
SQL学习一:ACID四个特性,CURD基本操作,常用关键字,常用聚合函数,五个约束,综合题
这篇文章是关于SQL基础知识的全面介绍,包括ACID特性、CURD操作、常用关键字、聚合函数、约束以及索引的创建和使用,并通过综合题目来巩固学习。
124 1
|
6月前
|
SQL JSON 分布式计算
ODPS SQL ——列转行、行转列这回让我玩明白了!
本文详细介绍了在MaxCompute中如何使用TRANS_ARRAY和LATERAL VIEW EXPLODE函数来实现列转行的功能。
|
6月前
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
|
8月前
|
SQL 存储 监控
SQL Server的并行实施如何优化?
【7月更文挑战第23天】SQL Server的并行实施如何优化?
204 13
|
8月前
|
SQL
解锁 SQL Server 2022的时间序列数据功能
【7月更文挑战第14天】要解锁SQL Server 2022的时间序列数据功能,可使用`generate_series`函数生成整数序列,例如:`SELECT value FROM generate_series(1, 10)。此外,`date_bucket`函数能按指定间隔(如周)对日期时间值分组,这些工具结合窗口函数和其他时间日期函数,能高效处理和分析时间序列数据。更多信息请参考官方文档和技术资料。
121 9
|
8月前
|
SQL 存储 网络安全
关系数据库SQLserver 安装 SQL Server
【7月更文挑战第26天】
102 6
|
7月前
|
SQL 数据挖掘 关系型数据库
SQL中的聚合函数:数据分析的强大工具
【8月更文挑战第31天】
242 0
|
7月前
|
SQL 数据挖掘 BI
【超实用技巧】解锁SQL聚合函数的奥秘:从基础COUNT到高级多表分析,带你轻松玩转数据统计与挖掘的全过程!
【8月更文挑战第31天】SQL聚合函数是进行数据统计分析的强大工具,可轻松计算平均值、求和及查找极值等。本文通过具体示例,展示如何利用这些函数对`sales`表进行统计分析,包括使用`COUNT()`、`SUM()`、`AVG()`、`MIN()`、`MAX()`等函数,并结合`GROUP BY`和`HAVING`子句实现更复杂的数据挖掘需求。通过这些实践,你将学会如何高效地应用SQL聚合函数解决实际问题。
90 0
|
7月前
|
SQL 安全 Java
驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“The server selected protocol version TLS10 is not accepted by client
驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“The server selected protocol version TLS10 is not accepted by client
626 0
|
6月前
|
SQL 数据库
数据库数据恢复—SQL Server数据库报错“错误823”的数据恢复案例
SQL Server附加数据库出现错误823,附加数据库失败。数据库没有备份,无法通过备份恢复数据库。 SQL Server数据库出现823错误的可能原因有:数据库物理页面损坏、数据库物理页面校验值损坏导致无法识别该页面、断电或者文件系统问题导致页面丢失。
146 12
数据库数据恢复—SQL Server数据库报错“错误823”的数据恢复案例

热门文章

最新文章