报表性能优化方案之多数据集实现层式报表

1. 问题描述
若报表使用的数据量是上百万条的话,以为报表展示的速度慢,可使用层式报表来提升报表展示速度。但由层式报表章节能够得知,层式报表必须是单数据集,如果多数据集的模板且数据量又很大,想要提升报表的查询速度要如何实现呢?html

2. 实现思路
在定义数据集时经过使用数据库自己的行序号或者使用数据库函数生成行序号(即行号)而且在where条件中经过页码参数使得行号在必定范围内显示,点击自定义的上一页下一页按钮时从新传入页码参数取出相应的数据。web

注:SQL Server2000没法生成行号,所以须要定义存储过程实现分页查询,如下具体介绍Access实现分页的步骤,SQL Server2005以及Oracle数据库实现分页的步骤有一点区别,如下会详细介绍。数据库

3. Access分页示例
3.1 新建模板
新建模板mutipage.cpt,为了加快展现速度,咱们可使用分页查询,获取每一个产品的详细信息并计算产品对应的订单中的应付金额,所以添加数据集时查询SQL语句为select 产品.产品ID,产品名称, 供应商ID , 类别ID, 单位数量, 产品.单价, 产品.库存量, 产品.订购量,sum(应付金额) as 应付款项 from 产品,订单,订单明细 where 产品.产品ID=订单明细.产品ID and 订单明细.订单ID=订单.订单ID and 产品.产品ID between 10*(${page}-1)+1 and 10*${page} group by 产品.产品ID,产品名称, 供应商ID , 类别ID, 单位数量, 产品.单价, 产品.库存量, 产品.订购量 order by 产品.产品ID,设置参数page的默认值为1,首次看到的是第一页,只查询出第1~20条记录;若page参数为2时,查询出第21~40条记录,即第二页内容。函数

注:这边定义报表每页显示10条数据,即ds1的查询SQL一次只取10条数据,从而加快报表展现速度。工具

3.2 自定义上一页、下一页按钮
使用分页查询后,报表须要根据page参数查询出行号在必定范围内的数据,当点击下一页时,page须要加1并传入报表查询出后10条记录;点击上一页时,page须要减1并传入报表查询出前10条记录。而报表内置的上一页下一页按钮没法作这些操做,所以须要自定义上一页下一页按钮。this

  • 在单元格中求出上一页、下一页页码的值orm

在工具栏中没法直接获取page参数的值,所以先在单元格中求出上一页下一页的页码值,而后再在工具栏按钮中获取单元格的值。htm

  • 自定义上一页下一页按钮ip

点击模板>模板web属性>分页预览设置分,选择为该模板单独设置,在工具栏中增长两个自定义按钮分别命名为上一页,下一页,是工具栏上只剩下以下图所示几个按钮。get

3.3 第一页与最后一页的处理
首次访问报表时,默认显示第一页page=1,此时上一页按钮应该是无效的,不然点击上一页按钮时(页码为0),此时查询行号在-9到0之间的记录将会出错;一样,显示到最后一页时需下一页按钮无效。即当上一页页码page-1=0时,上一页无效;当下一页页码page>总页数时,下一页无效。

  • 求出总页数

根据总记录数及每页显示条数,求出总页数。新增数据集ds2,SQL语句为:SELECT count(*) as 总数 FROM 产品,查询出产品表总条数,拖入单元格,以下

双击总数所在单元格弹出数据列设置对话框,选择高级>自定义显示,在自定义中填入公式:roundup($$$/10,0)求出总页数。

将第一行的行高设置为0,或者是隐藏:

上一页按钮设置:选中上一页自定义按钮,点击自定义JavaScript,在js中填入:

  1. var page= $("tr[tridx=0]","div.content-container").children().eq(0).html();    

  2. if(page==0)//若是报表显示第一页,则上一页不可用  

  3. this.setEnable(false);  

  4. else  

  5. window.location.href="${servletURL}?reportlet=doc/Advanced/multipage.cpt&page="+page;   

注:第一句是获取上一页页码(A1单元格)的值,其中最后的html()能够用Text()代替;第二句是从新加载报表并给page参数赋值。

上一页按钮设置:下一页按钮设置与上一页的js差很少,只须要获取B1的值就能够了,因此在js中填入:

  1. var page= $("tr[tridx=0]","div.content-container").children().eq(1).html();    

  2. var total=$("tr[tridx=0]","div.content-container").children().eq(2).html();    

  3. if(parseInt(page) > parseInt(total))//若是报表显示最后一页,则下一页不可用  

  4. {  

  5. this.setEnable(false);  

  6. }  

  7. else  

  8. window.location.href="${servletURL}?reportlet=doc/Advanced/multipage.cpt&page="+page;   

注:首次打开报表的时候,因为page参数是在数据集中定义的,数据集参数的默认值在第一个次打开报表时没办法传到单元格中,因此须要定义一个彻底同样的模板参数page,默认值设为1。这样,首次打开模板时,上一页按钮一样不可用。

分页预览,便可查看效果。mutipage.cpt

具体模板可参考:%FR_HOME%\WebReport\WEB-INF\reportlets\doc\Advanced\mutipage.cpt。

4. SQL Server2005示例
SQL Server2005使用ROW_NUMBER() OVER (ORDER BY 主键字段) AS rowno生成行号。

所以只须要修改数据集ds1查询SQL语句为select * from (SELECT *,ROW_NUMBER() OVER (ORDER BY year_school_id) AS rowno FROM year_school) as b where b.rowno between 20*(${page}-1)+1 and 20*${page}便可。

5. Oracle示例
Oracle数据库中自己有行序号ROWNUM,所以只须要将上例ds1数据集修改为以下:SELECT * FROM (select A.*,ROWNUM rn from (select * from year_school) A where ROWNUM <=${start}+20) where RN >=${start}便可。

注:ROWNUM只支持小于,大因而不支持的,所以要作如上定义。

相关文章
相关标签/搜索