http://www.cbf107.com/CBF107Item.aspx?ID=79c98c3e-aea2-46f9-baa7-1ccd067e2a81sql
SQLServer2005 Pivot 转置使用动态列(应用到视图)服务器
最近项目中用到Pivot 对表进行转置,遇到一些问题,主要是Pivot 转置的时候没有办法动态产生转置列名,而做视图的时候又很须要动态的产生这些列,百度上彷佛也没有找的很满意的答案,在google上搜到一老外的解决方案,如今本身总结了一下,但愿给用的上的朋友一些帮助。ide
1.建立表脚本测试
if exists (select 1google
from sysobjectsserver
where id = object_id('Insurances')io
and type = 'U')table
drop table Insurancestest
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(),1,'张三',300,'医疗保险')
insert into Insurances values (newid(),2,'李四',250,'养老保险')
insert into Insurances values (newid(),2,'李四',350,'医疗保险')
insert into Insurances values (newid(),3,'王二',150,'养老保险')
insert into Insurances values (newid(),3,'王二',300,'医疗保险')
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,Name,InsuranceMoney,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.偶的问题
这个语句中 医疗保险、养老保险 是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,Name,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 是我测试的连接服务器
也能够经过sp_helpserver 查看
下面这句话也很是重要,使用的朋友替换[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
That’s all