动态交叉表

/*-- 数据测试环境 --*/
if exists (select * from dbo.sysobjects where id = object_id(N'[tb]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [tb]
GO

create table tb(单位名称 varchar(10),日期 datetime,销售额 int)
insert into tb
 select 'A单位','2001-01-01',100
 union all select 'B单位','2001-01-02',101
 union all select 'C单位','2001-01-03',102
 union all select 'D单位','2001-01-04',103
 union all select 'E单位','2001-01-05',104
 union all select 'F单位','2001-01-06',105
 union all select 'G单位','2001-01-07',106
 union all select 'H单位','2001-01-08',107
 union all select 'I单位','2001-01-09',108
 union all select 'J单位','2001-01-11',109

/*-- 要求结果
日期       A单位  B单位 C单位 D单位 E单位  F单位 G单位 H单位 I单位 J单位  
---------- ----- ----- ----- ----- ----- ----- ----  ----  ---- ------
2001-01-01 100   0     0     0     0     0     0     0     0     0
2001-01-02 0     101   0     0     0     0     0     0     0     0
2001-01-03 0     0     102   0     0     0     0     0     0     0
2001-01-04 0     0     0     103   0     0     0     0     0     0
2001-01-05 0     0     0     0     104   0     0     0     0     0
2001-01-06 0     0     0     0     0     105   0     0     0     0
2001-01-07 0     0     0     0     0     0     106   0     0     0
2001-01-08 0     0     0     0     0     0     0     107   0     0
2001-01-09 0     0     0     0     0     0     0     0     108   0
2001-01-11 0     0     0     0     0     0     0     0     0     109
--*/


declare @sql varchar(8000)
set @sql='select 日期=convert(varchar(10),日期,120)'
select @sql=@sql+',['+单位名称
 +']=sum(case 单位名称 when '''+单位名称+''' then 销售额 else 0 end)'
from(select distinct 单位名称 from tb) a
exec(@sql+' from tb group by convert(varchar(10),日期,120)') 

该方法有个缺陷,@sql varchar(8000)能装下的字符总量是有限的,若select distinct 单位名称 from tb

产生的结果集很多,会导致@sql的字符长度超出8000

-------------------------------用游标来做

原数据表

id    员工姓名  所在部门   销售业绩

...    ......            服装部       ........

效果表

员工姓名  销售业绩(合计)   服装部  家电部 ......

                  9                            4             6

create procedure Cross

@strTabName as varchar(50)='销售',

@strCol as varchar(50)='所在部门',

@strGroup as varchar(50)='员工姓名',  //分组字段

@strNumber as varchar(50)='销售业绩' ,//被统计字段

@strSum as varchar(50)='Sum' //运算方式

as

declare @strSql as varchar(1000),@strTmpCol as varchar(100)

EXECUTE('DECLARE cross_cursor CURSOR FOR SELECT DISTINCT'+@strCol+'from'+@strTabName+' for read only') --生成游标

begin

SET nocount ON

SET @strsql='select'+@strGroup+','+@strSum+'('+@strNumber+') as ['+@strNumber+']'  //查询的前半段

OPEN cross_cursor

while(0=0)

BEGIN

FETCH NEXT FROM cross_cursor   //遍历游标,将列头信息放入变量@strTmpCol

INTO @strTmpCol

if (@@fetch_status<>0) break

SET @strsql=@strsql+','+@strSum+'(CASE'+@strCol+'WHEN'''+@strTmpCol+'''THEN'+@strNumber+'ELSE

Null END) AS [' +@strTmpCol+ ']'   //构造查询

END

SET @strsql=@strsql+'from'+@strTabname+'group by'+@strGroup   //查询结尾

EXCUTE(@strsql)     --执行

if @@error<>0 RETURN @@error    //如果出错,返回错误代码

CLOSE cross_cursor

DEALLOCATE cross_cursor RETURN 0  //释放游标,返回0表示成功

end

go

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值