格间计算性能提高方案

通常状况下,若是报表中存在不少格间计算(即单元格之间的关联计算),那么一般会影响报表性能。这是由于:sql

一、格间计算很难分步骤编写,致使运算过程很难优化。数据库

二、格间计算可能须要屡次遍历单元格集才能完成运算。性能

三、格间计算每每要利用较多隐藏格做为中间变量。而隐藏格除格值外,还记录了不少与显示相关的属性值,好比:字体、颜色、显示方式等。即使设置了单元格隐藏,但这些属性还在,依然会占用内存,影响计算速度。字体

不过在润乾报表的集算脚本支持下,这个问题可以获得很好的解决。下面咱们就经过一个典型的例子——《雇员销售状况排名》报表,来看下传统方式和润乾报表的对比:优化

imagepng

报表要求以下:设计

按照员工姓名排序,根据订单总价计算排名,而且计算“和上一名的差距”。blog

1、传统实现方式排序

一、首先定义 sql 数据集 ds1,其 sql 以下:内存

SELECT EMPLOYEE.EID,MAX(EMPLOYEE.NAME) 姓名,sum(订单明细. 数量 * 订单明细. 单价) 订单总价 FROM EMPLOYEE, 订单, 订单明细 WHERE  订单. 订单 ID = 订单明细. 订单 ID  AND  EMPLOYEE.EID = 订单. 雇员 ID group by EMPLOYEE.EID order by 姓名table

能够看到,为了让输出结果要按姓名排序,SQL 中要写做“ORDER BY 姓名”。

二、报表设计

imagepng

其中,

雇员姓名、订单总价:直接来自 sql。

排名:C2 单元格利用格间计算实现排名计算。计算当前订单总价的排名时,须要先找出全部订单总价中比本格值大的单元格,而后符合条件的单元格数加一就是排名。也就是说每计算一个雇员的排名,就要遍历一边全部的订单总价。

相似地,D2 计算“和上一名的差距”时还要再作一次按条件遍历。这个遍历还存在引用关系的处理,要等排名列计算完才能算差距列,但报表计算次序通常是从上到下的,中途处理引用关系会致使屡次失败的试算(试图计算某格,若是发现该格引用的格未计算就要存放等待着下一轮再计算),失败的试算会浪费大量时间。

上述格间计算对订单总价遍历了 n 次,n 是雇员个数,两个格间运算的整体复杂度是 2*N*N。

2、润乾报表方案

采用润乾报表方案(结合集算器实现),能够编写过程化的集算脚本代替格间计算,从而提高报表性能。

一、编写集算器脚本

对于本报表,编写脚本以下(保存为 sales.dfx):

  A
1 =connect(“demo”)
2 =A1.query(“SELECT EMPLOYEE.EID,MAX(EMPLOYEE.NAME) 姓名,sum(订单明细. 数量 * 订单明细. 单价) 订单总价,null 排名,0 和上一名的差距 FROM EMPLOYEE, 订单, 订单明细 WHERE  订单. 订单 ID = 订单明细. 订单 ID  AND  EMPLOYEE.EID = 订单. 雇员 ID group by EMPLOYEE.EID order by 订单总价 desc”)
3 =A1.close()
4 =A2.run(#: 排名,if(#!=1, 订单总价 [-1]- 订单总价,0): 和上一名的差距)
5 =A4.sort(姓名)
6 return A5

代码说明:

A1:链接数据库。

A2:用 sql 计算订单总价,并按照订单总价降序排序。

A3:关闭数据库。

A4:对 A2 循环计算,“排名”等于当前记录的行号 #,“和上一名的差距”等于用上一行的订单总价减去当前行的订单总价,若是是第一行就直接为 0。

A5:按照姓名从新排序。

A6:返回结果集给报表。

能够看到集算脚本仅用一次遍历加一次排序就完成了排名和上一名的差距的计算,也不存在试算以解决引用关系的问题,全部计算都能一次成功进行。本方案的总体复杂度是 N(遍历计算)+N*logN(排序),比以前的格间计算快得多。

二、配置报表数据集

在报表设计器中定义集算数据集,调用 sales.dfx:

imagepng

三、设计报表

设计表样以下:

imagepng

相关文章
相关标签/搜索