TA的每日心情 | 开心 2021-12-13 21:45 |
---|
签到天数: 15 天 [LV.4]偶尔看看III
|
PIVOT 用于将列值旋转为列名(即行转列),在 SQL Server 2000可以用聚合函数配合CASE语句实现
PIVOT 的一般语法是:PIVOT(聚合函数(列) FOR 列 in (…) )AS P
注意:PIVOT、UNPIVOT是SQL Server 2005 的语法,使用需修改数据库兼容级别(在数据库属性->选项->兼容级别改为 90 )
SQL2008 中可以直接使用
完整语法:


- table_source
- PIVOT(
- 聚合函数(value_column)
- FOR pivot_column
- IN(<column_list>)
- )
复制代码 View Code
UNPIVOT 用于将列明转为列值(即列转行),在SQL Server 2000可以用UNION来实现


- 完整语法:
- table_source
- UNPIVOT(
- value_column
- FOR pivot_column
- IN(<column_list>)
- )
复制代码
View Code
典型实例
一、行转列
1、建立表格
- IF OBJECT_ID("tb") IS NOT NULL DROP TABLE tb
- go
- CREATE TABLE tb(姓名 VARCHAR(10),课程 VARCHAR(10),分数 INT)
- insert into tb VALUES ("张三","语文",74)
- insert into tb VALUES ("张三","数学",83)
- insert into tb VALUES ("张三","物理",93)
- insert into tb VALUES ("李四","语文",74)
- insert into tb VALUES ("李四","数学",84)
- insert into tb VALUES ("李四","物理",94)
- go
- SELECT * FROM tb
- go
复制代码
姓名 课程 分数
---------- ---------- -----------
张三 语文 74
张三 数学 83
张三 物理 93
李四 语文 74
李四 数学 84
李四 物理 94
2、使用SQL Server 2000静态SQL


- SELECT 姓名,
- max(CASE 课程 WHEN"语文" THEN 分数 ELSE 0 END) 语文,
- max(CASE 课程 WHEN"数学" THEN 分数 ELSE 0 END) 数学,
- max(CASE 课程 WHEN"物理" THEN 分数 ELSE 0 END) 物理
- FROM tb
- GROUP BY 姓名
复制代码
View Code
3、使用SQL Server 2000动态SQL


- --SQL SERVER 2000动态SQL,指课程不止语文、数学、物理这三门课程。(以下同)
- --变量按sql语言顺序赋值
- declare@sqlvarchar(500)
- set@sql="select姓名"
- select@sql=@sql+",max(case课程when """+课程+""" then分数else 0 end)["+课程+"]"
- from(selectdistinct课程fromtb)a--同from tb group by课程,默认按课程名排序
- set@sql=@sql+" from tb group by姓名"
- exec(@sql)
-
- --使用isnull(),变量先确定动态部分
- declare@sqlvarchar(8000)
- select@sql=isnull(@sql+",","")+" max(case课程when """+课程+""" then分数else 0 end) ["+课程+"]"
- from(selectdistinct课程fromtb)asa
- set@sql="select姓名,"+@sql+" from tb group by姓名"
- exec(@sql)
复制代码
View Code
4、使用SQL Server 2005静态SQL
- SELECT * FROM tb pivot( MAX(分数) FOR 课程 IN (语文,数学,物理))a
复制代码
姓名 语文 数学 物理
---------- ----------- ----------- -----------
李四 74 84 94
张三 74 83 93
5、使用SQL Server 2005动态SQL
- --使用stuff()
- DECLARE @sql VARCHAR(8000)
- SET @sql="" --初始化变量 @sql
- SELECT @sql= @sql+"," + 课程 FROM tb GROUP BY 课程 --变量多值赋值
- SET @sql= STUFF(@sql,1,1,"")--去掉首个","
- SET @sql="select * from tb pivot (max(分数) for 课程 in ("+@sql+"))a"
- PRINT @sql
- exec(@sql)
- --或使用isnull()
- DECLARE @sql VARCHAR(8000)
- --获得课程集合
- SELECT @sql= ISNULL(@sql+",","")+课程 FROM tb
- GROUP BY 课程
- SET @sql="select * from tb pivot (max(分数) for 课程 in ("+@sql+"))a"
- exec(@sql)
复制代码
二、行转列结果加上总分、平均分
1、使用SQL Server 2000静态SQL


- --SQL SERVER 2000静态SQL
- select姓名,
- max(case课程when"语文"then分数else0end)语文,
- max(case课程when"数学"then分数else0end)数学,
- max(case课程when"物理"then分数else0end)物理,
- sum(分数)总分,
- cast(avg(分数*1.0)asdecimal(18,2))平均分
- fromtb
- groupby姓名
复制代码
View Code
姓名 语文 数学 物理 总分 平均分
---------- ----------- ----------- ----------- -----------
李四 74 84 94 252 84.00
张三 74 83 93 250 83.33
2、使用SQL Server 2000动态SQL


- --SQL SERVER 2000动态SQL
- declare@sqlvarchar(500)
- set@sql="select姓名"
- select@sql=@sql+",max(case课程when """+课程+""" then分数else 0 end)["+课程+"]"
- from(selectdistinct课程fromtb)a
- set@sql=@sql+",sum(分数)总分,cast(avg(分数*1.0) as decimal(18,2)) 平均分from tb group by姓名"
- exec(@sql)
复制代码
View Code
3、使用SQL Server 2005静态SQL
- SELECT m.* ,
- n.总分 ,
- n.平均分
- FROM ( SELECT *
- FROM tb PIVOT( MAX(分数) FOR 课程 IN ( 语文, 数学, 物理 ) ) a
- ) m ,
- ( SELECT 姓名 ,
- SUM(分数) 总分 ,
- CAST(AVG(分数 * 1.0) AS DECIMAL(18, 2)) 平均分
- FROM tb
- GROUP BY 姓名
- ) n
- WHERE m.姓名 = n.姓名
复制代码
4、使用SQL Server 2005动态SQL


- --使用stuff()
- DECLARE @sql VARCHAR(8000)
- SET @sql = ""
- --初始化变量@sql
- SELECT @sql = @sql + "," + 课程
- FROM tb
- GROUP BY 课程
- --变量多值赋值
- --同select @sql = @sql + ","+课程 from (select distinct 课程 from tb)a
- SET @sql = STUFF(@sql, 1, 1, "")
- --去掉首个","
- SET @sql = " select m.* , n.总分,n.平均分 from
- (select * from (select * from tb) a pivot (max(分数) for 课程 in (" + @sql
- + ")) b) m ,
- (select 姓名,sum(分数)总分, cast(avg(分数*1.0) as decimal(18,2)) 平均分 from tb group by 姓名) n
- where m.姓名= n.姓名"
- EXEC(@sql)
-
- --或使用isnull()
- DECLARE @sql VARCHAR(8000)
- SELECT @sql = ISNULL(@sql + ",", "") + 课程
- FROM tb
- GROUP BY 课程
- SET @sql = "select m.* , n.总分,n.平均分 from
- (select * from (select * from tb) a pivot (max(分数) for 课程 in (" + @sql
- + ")) b) m ,
- (select 姓名,sum(分数)总分, cast(avg(分数*1.0) as decimal(18,2)) 平均分 from tb group by 姓名) n
- where m.姓名= n.姓名"
- EXEC(@sql)
复制代码
View Code
二、列转行
1、建立表格
- IF OBJECT_ID("tb") IS NOT NULL DROP TABLE tb
- go
- CREATE TABLE tb(姓名 VARCHAR(10),语文 INT,数学 INT,物理 INT)
- INSERT INTO tb VALUES("张三",74,83,93)
- INSERT INTO tb VALUES("李四",74,84,94)
- go
- SELECT * FROM tb
复制代码
姓名 语文 数学 物理
---------- ----------- ----------- -----------
张三 74 83 93
李四 74 84 94
2、使用SQL Server 2000静态SQL


- --SQL SERVER 2000静态SQL。
- select*from
- (
- select姓名,课程="语文",分数=语文fromtb
- unionall
- select姓名,课程="数学",分数=数学fromtb
- unionall
- select姓名,课程="物理",分数=物理fromtb
- ) t
- orderby姓名,case课程when"语文"then1when"数学"then2when"物理"then3end
复制代码
View Code
姓名 课程 分数
---------- ---- -----------
李四 语文 74
李四 数学 84
李四 物理 94
张三 语文 74
张三 数学 83
张三 物理 93
2、使用SQL Server 2000动态SQL


- --SQL SERVER 2000动态SQL。
- --调用系统表动态生态。
- declare@sqlvarchar(8000)
- select@sql=isnull(@sql+" union all ","")+" select姓名, [课程]="
- +quotename(Name,"""")+" , [分数] = "+quotename(Name)+" from tb"
- fromsyscolumns
- whereName!="姓名"andID=object_id("tb")--表名tb,不包含列名为姓名的其他列
- orderbycolid
- exec(@sql+" order by姓名")
- go
-
复制代码
View Code
3、使用SQL Server 2005静态SQL
- --SQL SERVER 2005动态SQL
- SELECT 姓名 ,
- 课程 ,
- 分数
- FROM tb UNPIVOT ( 分数 FOR 课程 IN ( [语文], [数学], [物理] ) ) t
复制代码
4、使用SQL Server 2005动态SQL
- --SQL SERVER 2005动态SQL
- DECLARE @sql NVARCHAR(4000)
- SELECT @sql = ISNULL(@sql + ",", "") + QUOTENAME(name)
- FROM syscolumns
- WHERE id = OBJECT_ID("tb")
- AND name NOT IN ( "姓名" )
- ORDER BY colid
- SET @sql = "select 姓名,[课程],[分数] from tb unpivot ([分数] for [课程] in(" + @sql
- + "))b"
- EXEC(@sql)
复制代码
来自大神张志涛
|
|