加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

SQLServer行列转换 Pivot UnPivot

发布时间:2020-12-12 14:29:14 所属栏目:MsSql教程 来源:网络整理
导读:PIVOT 用于将列值旋转为列名(即行转列),在SQL Server 2000 可以用聚合函数配合 CASE 语句实现 PIVOT 的一般语法是: PIVOT ( 聚合函数(列) FOR 列 in (…) )ASP 完整语法: table_source PIVOT( 聚合函数( value_column ) FORpivot_column IN(column_li

PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现

PIVOT的一般语法是:PIVOT(聚合函数(列) FOR 列 in (…) )ASP

完整语法:

table_source

PIVOT(

聚合函数(value_column

FORpivot_column

IN(<column_list>)

)

?

UNPIVOT用于将列明转为列值(即列转行),在SQL Server 2000可以用UNION来实现

完整语法:

table_source

UNPIVOT(

value_column

FORpivot_column

IN(<column_list>)

)

?

注意:PIVOT、UNPIVOT是SQL Server2005 的语法,使用需修改数据库兼容级别
?
在数据库属性->选项->兼容级别改为? 90

?

典型实例

一、行转列

1、建立表格

ifobject_id('tb')isnotnulldroptabletb

go

createtabletb(姓名varchar(10),课程varchar(10),分数int)

insertintotbvalues('张三','语文',74)

insertintotbvalues('张三','数学',83)

insertintotbvalues('张三','物理',93)

insertintotbvalues('李四',74)

insertintotbvalues('李四',84)

insertintotbvalues('李四',94)

go

select*fromtb

go

姓名???????课程???????分数

---------- ---------------------

张三???????语文???????74

张三???????数学???????83

张三???????物理???????93

李四???????语文???????74

李四???????数学???????84

李四???????物理???????94

?

2、使用SQLServer 2000静态SQL

--c

select姓名,

?max(case课程when'语文'then分数else0end)语文,

?max(case课程when'数学'then分数else0end)数学,

?max(case课程when'物理'then分数else0end)物理

fromtb

groupby姓名

姓名???????语文????????数学????????物理

---------- ---------------------- -----------

李四???????74?????????84?????????94

张三???????74?????????83?????????93

?

3、使用SQLServer 2000动态SQL

--SQLSERVER 2000动态SQL,指课程不止语文、数学、物理这三门课程。(以下同)

--变量按sql语言顺序赋值

declare@sqlvarchar(500)

set@sql='select姓名'

select@sql=@sql+',max(case课程when'''+课程+'''?then分数else0 end)['+课程+']'

from(selectdistinct课程fromtb)a--fromtb group by课程,默认按课程名排序

set@sql=@sql+'from tb group by姓名'

exec(@sql)

?

--使用isnull(),变量先确定动态部分

declare@sqlvarchar(8000)

select@sql=isnull(@sql+',','')+'max(case课程when'''+课程+'''then分数else0 end) ['+课程+']'

from(selectdistinct课程fromtb)asa??????

set@sql='select姓名,'+@sql+'from tb group by姓名'

exec(@sql)

姓名???????数学????????物理????????语文

---------- ---------------------- -----------

李四???????84?????????94?????????74

张三???????83?????????93?????????74

?

4、使用SQLServer 2005静态SQL

select*fromtb?pivot(max(分数)for课程in(语文,数学,物理))a

?

5使用SQL Server2005动态SQL

--使用stuff()

declare@sqlvarchar(8000)

set@sql=''??--初始化变量@sql

select@sql=@sql+','+课程fromtbgroupby课程--变量多值赋值

set@sql=stuff(@sql,1,'')--去掉首个','

set@sql='select* from tb?pivot(max(分数)for课程in('+@sql+'))a'

exec(@sql)

?

--或使用isnull()

declare@sqlvarchar(8000)

–-获得课程集合

select@sql=isnull(@sql+','')+课程fromtbgroupby课程???????????

set@sql='select* from tb?pivot(max(分数)for课程in('+@sql+'))a'

exec(@sql)

?

二、行转列结果加上总分、平均分

1、使用SQLServer 2000静态SQL

--SQLSERVER 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姓名

姓名???????语文????????数学????????物理????????总分????????平均分

---------- ---------------------- ----------- -----------

李四???????74?????????84?????????94?????????252????????84.00

张三???????74?????????83?????????93?????????250????????83.33

?

2、使用SQLServer 2000动态SQL

--SQLSERVER 2000动态SQL

declare@sqlvarchar(500)

set@sql='select姓名'

select@sql=@sql+',max(case课程when'''+课程+'''?then分数else0 end)['+课程+']'

from(selectdistinct课程fromtb)a

set@sql=@sql+',sum(分数)总分,cast(avg(分数*1.0)as decimal(18,2))?????平均分fromtb group by姓名'

exec(@sql)

?

3、使用SQLServer 2005静态SQL

selectm.*,n.总分,n.平均分

from

(select*fromtb?pivot(max(分数)for课程in(语文,物理))a)m,

(select姓名,sum(分数)总分,cast(avg(分数*1.0)asdecimal(18,2))平均分

fromtb

groupby姓名)n

wherem.姓名=n.姓名

?

4、使用SQL Server2005动态SQL

--使用stuff()

--

declare@sqlvarchar(8000)

set@sql=''??--初始化变量@sql

select@sql=@sql+','+课程fromtbgroupby课程--变量多值赋值

--select@sql = @sql + ','+课程from(select distinct课程fromtb)a

set@sql=stuff(@sql,'

set@sql='selectm.*,n.总分,n.平均分from

(select *from (select * from tb) a pivot (max(分数)for课程in('+@sql+')) b) m,

(select姓名,sum(分数)总分,2))平均分fromtb group by姓名)n

wherem.姓名=n.姓名'

exec(@sql)

?

--或使用isnull()

declare@sqlvarchar(8000)

select@sql=isnull(@sql+','')+课程fromtbgroupby课程

set@sql='selectm.*,n.平均分from

(select *from (select * from tb) a pivot (max(分数)for课程in('+

?@sql+'))b) m,

(select姓名,2))平均分fromtb group by姓名)n

wherem.姓名=n.姓名'

exec(@sql)

?

二、列转行

1、建立表格

ifobject_id('tb')isnotnulldroptabletb

go

createtabletb(姓名varchar(10),语文int,数学int,物理int)

insertintotbvalues('张三',74,83,93)

insertintotbvalues('李四',84,94)

go

select*fromtb

go

姓名???????语文????????数学????????物理

---------- ---------------------- -----------

张三???????74?????????83?????????93

李四???????74?????????84?????????94

?

2、使用SQLServer 2000静态SQL

--SQLSERVER 2000静态SQL

select*from

(

?select姓名,课程='语文',分数=语文fromtb

?unionall

?select姓名,课程='数学',分数=数学fromtb

?unionall

?select姓名,课程='物理',分数=物理fromtb

)t

orderby姓名,case课程when'语文'then1when'数学'then2when'物理'then3end

姓名???????课程?分数

---------- ---------------

李四???????语文?74

李四???????数学?84

李四???????物理?94

张三???????语文?74

张三???????数学?83

张三???????物理?93

??

2、使用SQLServer 2000动态SQL

--SQLSERVER 2000动态SQL

--调用系统表动态生态。

declare@sqlvarchar(8000)

select@sql=isnull(@sql+'union all ','')+'select姓名,[课程]='

+quotename(Name,'''')+',[分数]= '+quotename(Name)+' fromtb'

fromsyscolumns

whereName!='姓名'andID=object_id('tb')--表名tb,不包含列名为姓名的其他列

orderbycolid

exec(@sql+'order by姓名')

go

?

3、使用SQLServer 2005静态SQL

--SQLSERVER 2005动态SQL

select姓名,课程,分数fromtbunpivot (分数for课程in([语文],[数学],[物理]))t

?

4、使用SQL Server2005动态SQL

--SQLSERVER 2005动态SQL

declare@sqlnvarchar(4000)

select@sql=isnull(@sql+','')+quotename(Name)

fromsyscolumns

whereID=object_id('tb')andNamenotin('姓名')

orderbyColid

set@sql='select姓名,[课程],[分数]from tb unpivot ([分数]for [课程]in('+@sql+'))b'

exec(@sql)


http://blog.sina.com.cn/s/blog_81b2b2a101010ka2.html

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读