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

SQLServer2005 Pivot 转置使用动态列

发布时间:2020-12-12 15:08:31 所属栏目:MsSql教程 来源:网络整理
导读:转载自:http://www.cbf107.com/CBF107Item.aspx?ID=79c98c3e-aea2-46f9-baa7-1ccd067e2a81 SQLServer2005 Pivot 转置使用动态列(应用到视图) 最近项目中用到 Pivot 对表进行转置,遇到一些问题,主要是 Pivot 转置的时候没有办法动态产生转置列名 , 而作

转载自:http://www.cbf107.com/CBF107Item.aspx?ID=79c98c3e-aea2-46f9-baa7-1ccd067e2a81
SQLServer2005 Pivot
转置使用动态列(应用到视图)

最近项目中用到 Pivot 对表进行转置,遇到一些问题,主要是 Pivot 转置的时候没有办法动态产生转置列名 , 而作视图的时候又很需要动态的产生这些列,百度上似乎也没有找的很满意的答案,在 google 上搜到一老外的解决方案,现在自己总结了一下,希望给用的上的朋友一些帮助。

https://www.52php.cn/res/2020/07-25/23/b5cde633ba9965011f86f59513f0381f.gif

?

?

1. 创建表脚本

?

if exists ( select 1

??????????? from ? sysobjects

?????????? where ? id = object_id ( 'Insurances' )

??????????? and ?? type = 'U' )

?? drop table Insurances

go

?

/*==============================================================*/

/* Table: Insurances??????????????????????????????????????????? */

/*==============================================================*/

create table Insurances (

?? RefID??????????????? uniqueidentifier ???? not null,

?? HRMS???????????????? nvarchar ( 20) ???????? null,

?? Name ???????????????? nvarchar ( 20) ???????? null,

?? InsuranceMoney?????? money ??????????????? null,

?? InsuranceName??????? nvarchar ( 100) ??????? not null,

?? constraint PK_INSURANCES primary key ( RefID)

)

go

?

?

2. 测试数据脚本

?

insert into Insurances values ( newid (), 1, ' 张三 ' , 200, ' 养老保险 ' )

insert into Insurances values ( newid (), 300, ' 医疗保险 ' )

insert into Insurances values ( newid (), 2, ' 李四 ' , 250, 350, 3, ' 王二 ' , 150, ' 养老保险 ' )

insert into Insurances values ( newid (), ' 医疗保险 ' )

?

3. 查询表数据

?

select HRMS, Name , InsuranceMoney, InsuranceName From Insurances

?

HRMS???????????????? Name???????????????? InsuranceMoney??????? InsuranceName

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

1??????????????????? 张三 ????????????????? 200.00??????????????? 养老保险

2??????????????????? 李四 ????????????????? 350.00??????????????? 医疗保险

2??????????????????? 李四 ????????????????? 250.00??????????????? 养老保险

1??????????????????? 张三 ????????????????? 300.00??????????????? 医疗保险

3??????????????????? 王二 ????????????????? 300.00??????????????? 医疗保险

3??????????????????? 王二 ????????????????? 150.00??????????????? 养老保险

?

4. 转置表数据

?

select * from

(

select HRMS, InsuranceName from Insurances

) p

Pivot (

sum ( InsuranceMoney)

FOR InsuranceName IN

( [ 医疗保险 ], [ 养老保险 ]))

as pvt

?

?

HRMS???????????????? Name???????????????? 医疗保险 ???????????????? 养老保险

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

2??????????????????? 李四 ????????????????? 350.00??????????????? 250.00

3????? ?????????????? 王二 ????????????????? 300.00??????????????? 150.00

1??????????????????? 张三 ????????????????? 300.00??????????????? 200.00

?

5. 偶的问题

?

?

https://www.52php.cn/res/2020/07-25/23/35f0ecd5b0aa97d3f0cece87346bde1f.gif

?

?

?

这个语句中 医疗保险、养老保险 SQL 语句中写死的,而且 Sql2005 中这个代码没有办法使用动态的查询结果集

?

5. 存储过程解决问题

?

所以如果要动态的完成个脚本,可以先拼出 SQL 然后通过 exec sp_executesql 执行

?

实现存储过程

?

create procedure InsurancePivot

as

Begin

??? DECLARE @ColumnNames VARCHAR ( 3000)

?

??? SET @ColumnNames= ''

?

??? SELECT

?????? @ColumnNames = @ColumnNames + '[' + InsuranceName + '],'

??? FROM

?????? (

?????? SELECT DISTINCT InsuranceName FROM Insurances

?????? ) t

?

??? SET @ColumnNames= LEFT( @ColumnNames, LEN ( @ColumnNames)- 1)

?

??? DECLARE @selectSQL NVARCHAR ( 3000)

?

??? SET @selectSQL=

??? 'SELECT HRMS,Name,{0} FROM

?????? (

?????? SELECT HRMS,InsuranceMoney,InsuranceName FROM Insurances

?????? ) p

??? ? Pivot( Max(InsuranceMoney)? For InsuranceName in ({0})) AS pvt

?????? ORDER BY HRMS'

?

??? SET @selectSQL= REPLACE ( @selectSQL, '{0}' , @ColumnNames)

?

??? exec sp_executesql @selectSQL

end

?

测试存储过程:

?

exec InsurancePivot

?

HRMS???????????????? Name???????????????? 养老保险 ???????????????? 医疗保险

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

1??????????????????? 张三 ????????????????? 200.00??????????????? 300.00

2??????????????????? 李四 ????????????????? 250.00??????????????? 350.00

3??????????????????? 王二 ????????????????? 150.00??????????????? 300.00

?

?

6. 关于视图的新问题和解决方案

?

在视图中没有办法直接调用这个存储过程,但是我们在做程序、做报表的时候又非常需要

?

其实可以通过 OPENQUERY 来实现(这是一个非正规的解决方式,但目前可以实现)

(另外可以使用 OPENROWSET, 但是参数太多偶放弃了)

?

使用 OPENQUERY 的格式是: OPENQUERY([ 链接服务器 ],’sql 语句 ’)

?

因为是当前数据的视图, 链接服务器可以通过属性查看, MSCBF107 是我测试的链接服务器

?

https://www.52php.cn/res/2020/07-25/23/2668d5f43df8c95e3aa15c989a03c995.gif

?

https://www.52php.cn/res/2020/07-25/23/6593d51e60091df4f933a7e9b5097f53.gif

?

?

也可以通过 sp_helpserver 查看

?

https://www.52php.cn/res/2020/07-25/23/8562cecb075b246e6341cd140b171eed.gif

?

?

下面这句话也非常重要,使用的朋友替换 [MSCBF107] ok 了,否则使用 OPENQUERY 会出现 未将服务器 'MSCBF107' 配置为用于 DATA ACCESS

?

sp_serveroption [MSCBF107],'Data Access','True'

?

创建视图如下:

?

?

create view InsurancePivotView

as

select * From OPENQUERY ( [MSCBF107], N'SET FMTONLY OFF;exec test.dbo.InsurancePivot' )

?

?

测试视图就可以得到想要的结果了

?

select * from InsurancePivotView

(编辑:李大同)

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

    推荐文章
      热点阅读