一个动态交叉报表的例子
2007-05-26 16:27
423 查看
原文http://community.csdn.net/Expert/topic/5371/5371292.xml?temp=.5765955
表1(制造商号码作为主键) 制造商号码 制造商名 A1 Aname1 A2 Aname2 A3 Aname3 A4 Aname4 B1 Bname1 B2 Bname2 B3 Bname3
表2(制造商号码和商品号码联合作为主键) 制造商号码 商品号码 产量 A1 S1 1 A1 S2 2 A2 S2 3 A2 S3 4 A3 S1 5 A3 S4 6 A4 S3 7 A4 S5 8 B1 S6 9 B2 S6 10 B3 S1 11
要求做两个存储过程 1。存储过程CreateTempTable,一个Varchar型参数,例如: CreateTempTable 'A' 则生成下表 商品号码 制造商A1 制造商A2 制造商A3 制造商A4 S1 1 0 5 0 S2 2 3 0 0 S3 0 4 0 7 S4 0 0 6 0 S5 0 0 0 8 CreateTempTable 'B' 则生成下表 商品号码 制造商B1 制造商B2 制造商B3 S1 0 0 11 S6 9 10 0 就是生成以输入参数开头的商品产量表,典型的行列转置问题,每次生成的表的列数和列名都不固定。 2。在1生成的表中任意改产量,用一个WriteSourceTable的存储过程,更新回表2
要求用尽量少的语句实现,语句(注意:不是指代码字符数)越少,分数越高。 (以SQL语句数量决定,比如Create Table可能要写很多行,但还是看作一条SQL语句。)
-----------------------------------------------------------------------
--创建测试环境 create table 表1(制造商号码 varchar(20) primary key,制造商名 varchar(20)) create table 表2(制造商号码 varchar(20),商品号码 varchar(20),产量 int)
--插入测试数据 insert 表1(制造商号码,制造商名) select 'A1','Aname1' union all select 'A22','Aname2' union all select 'A333','Aname3' union all select 'A4444','Aname4' union all select 'B1','Bname1' union all select 'B2','Bname2' union all select 'B3','Bname3'
insert 表2(制造商号码,商品号码,产量) select 'A1','S1','1' union all select 'A1','S2','2' union all select 'A22','S2','3' union all select 'A22','S3','4' union all select 'A333','S1','5' union all select 'A333','S4','6' union all select 'A4444','S3','7' union all select 'A4444','S5','8' union all select 'B1','S6','9' union all select 'B2','S6','10' union all select 'B3','S1','11' go --第一题,CreateTempTable动态创建表 create proc CreateTempTable @str varchar(8000),@tablename sysname as begin set nocount on set xact_abort on
declare @col varchar(8000),@sql varchar(8000) select @col = 'create table '+ @tablename+ '(商品号码 varchar(20)' ,@sql = 'select 商品号码'
select @col = @col + ',制造商' + 制造商号码 + ' varchar(20)' ,@sql = @sql + ',sum(case 制造商号码 when ''' + 制造商号码 + ''' then 产量 else 0 end) as 制造商' + 制造商号码 from 表1 where 制造商号码 in (select 制造商号码 from 表2 where 制造商号码 like '%'+ @str+'%') order by 制造商号码
select @col = @col + ')',@sql = @sql + ' from 表2 where 制造商号码 like ''%'' +''' + @str + '''+ ''%'' group by 商品号码' ,@sql = replace(@sql,'''','''''')
--事务保护 begin tran if exists (select 1 from sysobjects where id = object_id(@tablename) and type = 'U') exec('drop table '+ @tablename) exec (@col) exec ('insert '+ @tablename + ' exec ('''+@sql+''')') commit tran end go --测试 exec CreateTempTable 'A1','tablename'
select * from tablename /*--测试结果 商品号码 制造商A1 -------------------- -------------------- S1 1 S2 2 */
--第二题 go create proc WriteSourceTable @tablename sysname as begin set nocount on set xact_abort on if not exists (select 1 from sysobjects where id = object_id(@tablename) and type = 'U') begin select '没有这个表!' return end
declare @sql varchar(8000) set @sql = ''
--事务保护,防止其它事务更改表@tablename的架构 begin tran exec ('dbcc lockobjectschema (' + @tablename + ')')
select @sql = @sql + ' union all select ''' + right(name,len(name)-3) + ''' as 制造商,商品号码,' + name + ' as 产量 from '+ @tablename from( select name from syscolumns where id = object_id(@tablename) and name like '制造商%' ) _x select @sql = stuff(@sql,1,11,'') create table #t(制造商号码 varchar(20),商品号码 varchar(20),产量 int) insert #t exec(@sql) commit tran
begin tran update _a set _a.产量 = _b.产量 from 表2 _a join #t _b on _b.制造商号码 = _a.制造商号码 and _b.商品号码 = _a.商品号码 insert 表2 select * from #t _t where not exists( select 1 from 表2 t where t.制造商号码 = _t.制造商号码 and t.商品号码 = _t.商品号码 ) and _t.产量 > 0 commit tran
drop table #t end go
--修改数据 update tablename set 制造商A1 = 100
select * from tablename /* 商品号码 制造商A1 -------------------- -------------------- S1 100 S2 100 */
--执行存储过程 exec WriteSourceTable 'tablename'
--查看结果 select * from 表2
--结果 /* 制造商号码 商品号码 产量 -------------------- -------------------- ----------- A1 S1 100 A1 S2 100 A22 S2 3 A22 S3 4 A333 S1 5 A333 S4 6 A4444 S3 7 A4444 S5 8 B1 S6 9 B2 S6 10 B3 S1 11 */
go --删除测试环境 drop table 表2 drop table 表1 drop proc CreateTempTable,WriteSourceTable
相关文章推荐
- 一个动态交叉分片报表的几种实现方法
- 一个简单的UI动态查询报表例子
- C# 一个通过.xsd文件动态绑定数据的水晶报表
- 一个动态菜单的例子(downmoon)
- DataGrid动态添加模板列的一个例子
- 数组不是指针——数组地址不能动态分配空间,一个小例子关于指针移动,以及malloc
- 一个动态编译的简单例子
- PB动态生成数据窗口的一个例子
- CGLib动态代理原理及实现的一个小例子
- sqlserver一个动态交叉表的范例
- 通过freemarker生成一个超简单的动态表单例子
- 行值动态变化的交叉报表处理示例.sql
- 自定义动态生成页面打印以及打印预览的一个实现例子
- 报一个比较难以描述的问题【关键字 报表 数据库行列转换 多表交叉查询】
- 一个简单打开D盘所有文件夹和文件的例子以及动态创建双击事件
- 一个动态添加panel 和 删除panel的例子
- .net 2.0学习动态语言的另外一个例子?
- sqlserver一个动态交叉表的范例
- struts资源文件的中文解决方法,附带Struts1.2动态FormBean加验证功能的一个例子
- 【转】JDK 6动态编译类的一个例子