SQLServer2005 Pivot 转置使用动态列

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

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

SQLServer2005 Pivot 转置使用动态列_第1张图片

 

 

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 (), 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

你可能感兴趣的:(SQLServer2005 Pivot 转置使用动态列)