多数据集实现层式报表

目录:

  1. 问题描述
  2. 实现思路
  3. Access分页示例
  4. SQL Server示例
  5. Oracle示例
  6. Mysql示例
  7. 问题描述
    若报表使用的数据量是上百万条的话,觉得报表展现的速度慢,可以使用层式报表来提高报表展现速度。但由层式报表章节可以得知,层式报表必须是单数据集,若是多数据集的模板且数据量又很大,想要提高报表的查询速度要如何实现呢?
  8. 实现思路
    在定义数据集时通过使用数据库本身的行序号或者使用数据库函数生成行序号(即行号)并且在where条件中通过页码参数使得行号在一定范围内显示,点击自定义的上一页下一页按钮时重新传入页码参数取出相应的数据。
    注:SQL Server2000无法生成行号,因此需要定义存储过程实现分页查询,以下具体介绍Access实现分页的步骤,SQL Server2005以及Oracle数据库实现分页的步骤有一点区别,以下会详细介绍。
  9. Access分页示例
    3.1 新建模板
    新建模板mutipage.cpt,为了加快展示速度,我们可以使用分页查询,获取每个产品的详细信息并计算产品对应的订单中的应付金额,因此添加数据集ds1时查询SQL语句为select 产品.产品ID,产品名称, 供应商ID , 类别ID, 单位数量, 产品.单价, 产品.库存量, 产品.订购量,sum(应付金额) as 应付款项 from 产品,订单,订单明细 where 产品.产品ID=订单明细.产品ID and 订单明细.订单ID=订单.订单ID and 产品.产品ID between 10*( p a g e − 1 ) + 1 a n d 10 ∗ {page}-1)+1 and 10* page1)+1and10{page} group by 产品.产品ID,产品名称, 供应商ID , 类别ID, 单位数量, 产品.单价, 产品.库存量, 产品.订购量 order by 产品.产品ID,设置参数page的默认值为1,首次看到的是第一页,只查询出第120条记录;若page参数为2时,查询出第2140条记录,即第二页内容。
    注:这边定义报表每页显示10条数据,即ds1的查询SQL一次只取10条数据,从而加快报表展示速度。
    3.2 自定义上一页、下一页按钮
    使用分页查询后,报表需要根据page参数查询出行号在一定范围内的数据,当点击下一页时,page需要加1并传入报表查询出后10条记录;点击上一页时,page需要减1并传入报表查询出前10条记录。而报表内置的上一页下一页按钮无法做这些操作,因此需要自定义上一页下一页按钮。
    (1)在单元格中求出上一页、下一页页码的值
    在工具栏中无法直接获取page参数的值,因此先在单元格中求出上一页下一页的页码值,然后再在工具栏按钮中获取单元格的值。
    (2)自定义上一页下一页按钮
    点击模板>模板web属性>分页预览设置,选择为该模板单独设置,在工具栏中增加两个自定义按钮分别命名为上一页,下一页,使工具栏上只剩下如下图所示几个按钮。

3.3 第一页与最后一页的处理
首次访问报表时,默认显示第一页page=1,此时上一页按钮应该是无效的,否则点击上一页按钮时(页码为0),此时查询行号在-9到0之间的记录将会出错;同样,显示到最后一页时需下一页按钮无效。即当上一页页码page-1=0时,上一页无效;当下一页页码page>总页数时,下一页无效。
求出总页数
根据总记录数及每页显示条数,求出总页数。新增数据集ds2,SQL语句为:SELECT count(*) as 总数 FROM 产品,查询出产品表总条数,拖入单元格,如下
双击总数所在单元格弹出数据列设置对话框,选择高级>自定义显示,在值中填入公式:roundup($$$/10,0)求出总页数。
将第一行的行高设置为0,或者是隐藏:
上一页按钮设置:选中上一页自定义按钮,点击自定义事件,在js中填入:

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

if(page==0)//如果报表显示第一页,则上一页不可用

this.setEnable(false);

else

window.location.href="${servletURL}?reportlet=doc/Advanced/multipage.cpt&page="+page;
注:第一句是获取上一页页码(A1单元格)的值,其中最后的html()可以用Text()代替;第二句是重新加载报表并给page参数赋值。
注:若获取的页码时合并了单元格,那么需要注意获取的单元格。举个例子,如果需要获取D1单元格中的值,那么在不合并单元格的情况下,eq后面的列号应该写3;如果ABC列单元格合并了,那么他们其实是作为了一个整体算列数,这时获取D1的值,eq后面的列数就需要写1。
上一页按钮设置:下一页按钮设置与上一页的js差不多,只需要获取B1的值就可以了,所以在js中填入:

var page= ( " t r [ t r i d x = 0 ] " , " d i v . c o n t e n t − c o n t a i n e r " ) . c h i l d r e n ( ) . e q ( 1 ) . h t m l ( ) ; v a r t o t a l = ("tr[tridx=0]","div.content-container").children().eq(1).html(); var total= ("tr[tridx=0]","div.contentcontainer").children().eq(1).html();vartotal=(“tr[tridx=0]”,“div.content-container”).children().eq(2).html(); if(parseInt(page) > parseInt(total))//如果报表显示最后一页,则下一页不可用 { this.setEnable(false); } else window.location.href="KaTeX parse error: Expected 'EOF', got '&' at position 50: …d/multipage.cpt&̲page="+page; …{page}-1)+1 and 20* p a g e 方 案 二 : 使 用 N O T I N / T O P 数 据 集 d s 1 查 询 S Q L 语 句 : s e l e c t t o p 20 ∗ f r o m 产 品 w h e r e 产 品 i d n o t i n ( s e l e c t t o p ( 20 ∗ ( {page} 方案二:使用NOT IN/TOP 数据集ds1查询SQL语句: select top 20 * from 产品 where 产品id not in (select top (20*( page使NOTIN/TOPds1SQLselecttop20fromwhereidnotin(selecttop(20({page}-1)) 产品id from 产品 order by 产品id) order by 产品id
方案三:使用NOT EXIST
数据集ds1查询SQL语句:
select top 20 * from 产品 where not exists (select 1 from (select top (20*( p a g e − 1 ) ) 产 品 i d f r o m 产 品 o r d e r b y 产 品 i d ) a w h e r e a . 产 品 i d = 产 品 . 产 品 i d ) o r d e r b y 产 品 i d 注 : 推 荐 使 用 方 案 一 的 分 页 方 法 。 R O W N U M B E R ( ) 只 支 持 S Q L 2005 及 以 上 版 本 , N O T E X I S T S 执 行 效 率 比 N O T I N 强 一 点 。 5. O r a c l e 示 例 O r a c l e 数 据 库 中 本 身 有 行 序 号 R O W N U M , 因 此 只 需 要 将 上 例 d s 1 数 据 集 修 改 成 如 下 : S E L E C T ∗ F R O M ( s e l e c t A . ∗ , R O W N U M r n f r o m ( s e l e c t ∗ f r o m 产 品 ) A w h e r e R O W N U M < = {page}-1)) 产品id from 产品 order by 产品id)a where a.产品id=产品.产品id) order by 产品id 注:推荐使用方案一的分页方法。ROW_NUMBER()只支持SQL2005及以上版本,NOT EXISTS执行效率比NOT IN强一点。 5. Oracle示例 Oracle数据库中本身有行序号ROWNUM,因此只需要将上例ds1数据集修改成如下:SELECT * FROM (select A.*,ROWNUM rn from (select * from 产品) A where ROWNUM <= page1))idfromorderbyid)awherea.id=.id)orderbyid使ROWNUMBER()SQL2005NOTEXISTSNOTIN5.OracleOracleROWNUMds1SELECTFROM(selectA.,ROWNUMrnfrom(selectfrom)AwhereROWNUM<={page}+20) where RN >=${page}即可。
注:ROWNUM只支持小于,大于是不支持的,因此要做如上定义。
6. Mysql示例
MySQL数据库分页首选LIMIT语法,因此只需要将上例ds1数据集修改成如下:

方案一:LIMIT

数据集ds1查询SQL语句:

SELECT * FROM 产品 ORDER BY 产品id LIMIT ${t},20

并给参数t赋值公式:20*($page-1) ,如下图所示:

注:mysql数据库中sql语句不能进行直接运算,因此将运算公式赋值给变量t。

数据集ds1查询SQL语句:

SELECT * FROM 产品 WHERE 产品id >=(SELECT 产品id FROM 产品 ORDER BY 产品id LIMIT ${t}, 1) LIMIT 20

并给参数t赋值为公式:20*($page-1)

注:LIMIT 接受一个或两个数字参数,参数必须是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目。初始记录行的偏移量是0。

主题:
标签: 已验证 9.0验证

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值