`
hjoo
  • 浏览: 73508 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

用存储过程实现交叉报表(动态列)

    博客分类:
  • J2SE
阅读更多
由于Birt不支持交叉报表(虽然能勉强实现,但十分麻烦),因此这几天郁闷死我了!最后决定在数据库里用存储过程先生成交叉表,然后直接用JSP显示出来。系统虽然是用的struts+spring+hibernate架构的,但为了简单起见就偷懒了!

记录下这些内容方便自己日后查看,出现一次意外就是把数据库还原回来,结果存储过程全没了白忙一场,还好印象比较深又搞定了!

由于我是好几张表关联,大概有6张吧,哈哈,所以先建个视图trainView把6张表全联接起来,代码:
SELECT tb.id, tb.sex, tb.age, tb.trainDays, tb.trainYear, p.PoliceNum, p.Name, p.deptname, 
      p.GradationNum, tm.trainMark, ti.name AS itemName, ti.code, ti.parentId
FROM dbo.TrainBase tb INNER JOIN
          (SELECT p.*, d .deptname
         FROM Misperson_Misdept pd LEFT JOIN
               misperson p ON pd.misperson_id = p.id LEFT JOIN
               misdept d ON pd.misdept_id = d .id) p ON 
      tb.personId = p.ID LEFT OUTER JOIN
      dbo.TrainMark tm ON tb.id = tm.trainId INNER JOIN
      dbo.TrainItem ti ON tm.itemId = ti.id


各张表的表结构在此就不给出了!

然后是存储过程trainReport的代码:
CREATE PROCEDURE trainReport
	@trainYear varchar(20)
 AS
	declare @sql varchar(8000)

set @sql = 'select name as 姓名,sex as 性别,age as 年龄,policeNum as 警号,deptName as 所在单位,trainDays as 参加集中训练时间,'

select @sql = @sql + 'sum(case itemName when '''+itemName+''' then trainMark else 0 end) as '''+itemName+''','
	from (select distinct itemName from trainView) as a
select @sql = left(@sql,len(@sql)-1) + ',trainYear,GradationNum from trainView where trainYear='+@trainYear+' group by name,sex,age,policeNum,deptName
,trainDays,trainYear,GradationNum order by GradationNum'
exec(@sql)
GO


代码都没有经过优化,以实现为第一考虑!
显示部分就直接在JSP里用JDBC调用存储过程,然后显示列和行
部分代码如下:
<%
			String trainYear = request.getParameter("trainYear");
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver")
					.newInstance();
			String url = "jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=YJGA";
			String user = "sa";
			String password = "sa";
			Connection conn = DriverManager.getConnection(url, user, password);
			CallableStatement proc = conn
					.prepareCall("execute trainReport '" + trainYear + "'");
			ResultSet rs = proc.executeQuery();
			ResultSetMetaData dm = rs.getMetaData();
		%>

动态显示列名:
<%
					for(int i = 1; i <= dm.getColumnCount()-2; i++){
						if(i==6){
							out.print("<td class=xl width=200>" + dm.getColumnName(i) + "</td>");
						}else{
							out.print("<td class=xl width=100>" + dm.getColumnName(i) + "</td>");
						}
					}
				%>


然后是显示记录:
<%
				while(rs.next()){
					out.print("<tr height=25 style='mso-height-source:userset;height:23.25pt'>");
					for(int i = 1; i <= dm.getColumnCount()-2; i++){
						out.print("<td class=xl>" + rs.getString(i) + "</td>");
					}
					out.print("</tr>");
				}
			%>		


最有用的部分就是存储过程trainReport,实现了将动态的行转为列的功能!
最终结果如下,参加集中训练时间后面那些列是根据每年的训练项目动态变化的!

姓名  性别 年龄 警号  所在单位 参加集中训练时间 测试项目 其它项目 现场急救
陈龙  男  25  990151 计通科  15       90    50    0
胡建欧 男  25  990150 计通科  15       0     90    80
分享到:
评论
1 楼 w156445045 2012-07-22  
博主您好,我现在碰到了和您一样的问题。我用iReport试着做了下,没做出来。
我动态显示页面,显示记录,这个不会呢,不知道是啥意思呢,谢谢!

相关推荐

    存储过程后台实现报表

    存储过程动态sql,交叉报表 动态实现报表

    Sqlserver2000经典脚本

    │ 6.3.3 行值动态变化的交叉报表处理示例(转换多列).sql │ │ 6.3.3 行值动态变化的交叉报表处理示例.sql │ │ 6.3.4 化解字符串不能超过8000的方法.sql │ │ 6.3.5 特殊的交叉报表处理示例.sql...

    经典SQL脚本大全

    │ │ 6.3.3 行值动态变化的交叉报表处理示例(转换多列).sql │ │ 6.3.3 行值动态变化的交叉报表处理示例.sql │ │ 6.3.4 化解字符串不能超过8000的方法.sql │ │ 6.3.5 特殊的交叉报表处理示例.sql │ │ 6.4.1 ...

    Anycell Report中式报表组件1.72

    改进了报表存储格式,占用空间更小,兼容以前版本的格式。4.修正了合计中的bug。5.正确支持纵向合并分组报表 http://www.efile.com.cn/eFile/syy_tfsky/group1.jpg关于 AC Report:AC Report是一套功能强大、基于表格...

    VFP]对报表.FRX文件的分析

    17 ENVIRON L 1 是否报表运行环境(.T.时) 18 BOXCHAR C 1 画框字符 19 FILLCHAR C 1 表达式类型(C,N,D等,文字型的为空) 20 TAG M 10 (当该记录为记录环境的记录时,该字段储存打印信息等;记录数据库时,储存数据库...

    sqlserver2000基础(高手也有用)

    6.3.5 特殊的交叉报表 191 6.4 典型数据统计案例 193 6.4.1 库存明细账查询 193 6.4.2 同期及上期数据对比 197 6.4.3 动态分组统计 199 6.4.4 销售排行榜 200 第 7 章 分页处理 205 7.1 应用程序中...

    Access 2000数据库系统设计(PDF)---001

    26411.8.2 基于窗体的更新 26411.8.3 用SQL语句进行更新 26411.8.4 用SQL Server存储过程进行更新 265第三部分 设计窗体和报表第12章 创建和使用窗体 26712.1 理解Access窗体和控件的角色 26712.2 使用窗体向导创建...

    Access 2000数据库系统设计(PDF)---002

    26411.8.2 基于窗体的更新 26411.8.3 用SQL语句进行更新 26411.8.4 用SQL Server存储过程进行更新 265第三部分 设计窗体和报表第12章 创建和使用窗体 26712.1 理解Access窗体和控件的角色 26712.2 使用窗体向导创建...

    Access 2000数据库系统设计(PDF)---018

    26411.8.2 基于窗体的更新 26411.8.3 用SQL语句进行更新 26411.8.4 用SQL Server存储过程进行更新 265第三部分 设计窗体和报表第12章 创建和使用窗体 26712.1 理解Access窗体和控件的角色 26712.2 使用窗体向导创建...

    Access 2000数据库系统设计(PDF)---003

    26411.8.2 基于窗体的更新 26411.8.3 用SQL语句进行更新 26411.8.4 用SQL Server存储过程进行更新 265第三部分 设计窗体和报表第12章 创建和使用窗体 26712.1 理解Access窗体和控件的角色 26712.2 使用窗体向导创建...

    Access 2000数据库系统设计(PDF)---011

    26411.8.2 基于窗体的更新 26411.8.3 用SQL语句进行更新 26411.8.4 用SQL Server存储过程进行更新 265第三部分 设计窗体和报表第12章 创建和使用窗体 26712.1 理解Access窗体和控件的角色 26712.2 使用窗体向导创建...

    Access 2000数据库系统设计(PDF)---020

    26411.8.2 基于窗体的更新 26411.8.3 用SQL语句进行更新 26411.8.4 用SQL Server存储过程进行更新 265第三部分 设计窗体和报表第12章 创建和使用窗体 26712.1 理解Access窗体和控件的角色 26712.2 使用窗体向导创建...

    Access 2000数据库系统设计(PDF)---009

    26411.8.2 基于窗体的更新 26411.8.3 用SQL语句进行更新 26411.8.4 用SQL Server存储过程进行更新 265第三部分 设计窗体和报表第12章 创建和使用窗体 26712.1 理解Access窗体和控件的角色 26712.2 使用窗体向导创建...

    Access 2000数据库系统设计(PDF)---012

    26411.8.2 基于窗体的更新 26411.8.3 用SQL语句进行更新 26411.8.4 用SQL Server存储过程进行更新 265第三部分 设计窗体和报表第12章 创建和使用窗体 26712.1 理解Access窗体和控件的角色 26712.2 使用窗体向导创建...

Global site tag (gtag.js) - Google Analytics