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