复杂数据源是报表开发的常见问题,比如不同数据库表先进行join运算,再进行后续的过滤分组排序等运算。JasperReport/Birt等报表工具有virtual data source或table join,可以一定程度地实现多数据源join后计算,但掌握起来并不容易。
集算器具有结构化强计算引擎,支持多样性数据源,集成简单,可以协助报表工具方便地实现此类需求,下面通过一个例子来说明多数据源join后计算的过程。
Sales是mysql数据库中的表,存储着多名销售员每天的多个订单,其中字段SellerId是销售员编号。emp是mssql数据库中的表,存储着销售员信息,其中字段EId是销售员编号,Name是销售员名字,Dept是部门名称。现在需要在报表中展现:订单编号、日期、金额、销售员名字、部门名称,条件是:订单日期在最近N天(比如30天)或者订单属于某几个受关注的部门(比如Markeding和Finance)。
由于订单编号、日期、金额来自于表sales,而销售员名字、部门名称来自于表emp,因此要进行不同数据库之间join运算,join之后还要进行条件过滤。部分源数据如下:
表sales
表emp
集算器代码:
A1=myDB1.query("select * from sales")
这句代码从数据源myDB1查询出sales表的记录,myDB1指向mysql数据库。函数query用来执行SQL查询,可以接收外部参数。A1的计算结果如下:
A2=myDB2.query("select * from emp")
这句代码从数据源myDB2查询出emp表的记录,myDB2指向mssql数据库。
A3=A1.switch(SellerId,A2:EId)
上述代码将A1中的SellerId字段替换成A2中对应的记录,关联字段为EId。A3的计算结果如下(蓝色字体表示该数据项包含下级成员):
当A2中找不到对应的记录时,函数switch默认保留A1中记录,对应的SellerId显示为空,效果类似于左连接。如果想进行内连接,应当使用选项@i,形如:A1.switch@i(SellerId,A2:EId)
A4=A3.select(OrderDate>=after(date(now()),days*-1)|| depts.array().pos(SellerId.Dept))
上述代码可对关联结果进行过滤,条件有2个,第1个条件是:订单日期在最近N天(对应参数days),表达式为OrderDate>=after(date(now()),days*-1)。第2个条件是:订单属于某几个受关注的部门(对应参数depts),表达式是depts.array().pos(SellerId.Dept)。运算符||表示逻辑关系“或”。
函数now可以取当前时间,函数date将当前时间转为日期,函数after可以算出相对时间,比如after("2015-01-30",-30)表示将时间后退30天,即2015-01-01。使用不同的选项,函数after还能以年、季、月、秒为单位计算相对时间。
函数array可以按分隔符将字符串变成集合,比如"Marketing,Finance".array()等于["Marketing ","Finance"]。函数array的默认分隔符是逗号,也可以指定其他分隔符。函数pos可以找出成员在集合中的位置,比如["Marketing ","Finance"].pos("Finance")等于2,在逻辑关系中等于true。如果成员不在集合中,则返回null,在逻辑关系中等于false。
值得注意的是SellerId.Dept这种用法,这表示SellerId字段对应的记录的Dept字段。可以看到,用switch替换字段后,表之间的关联关系就可以用对象的方式来访问,这种方式直观简单,进行多表多层关联时会体现得更明显。
Days和depts都是来自于报表的参数,如果分别输入30、"Marketing,Finance",则A4的结果如下:
A5=A4.new(OrderID,OrderDate,Amount,SellerId.Name:Name,SellerId.Dept:Dept)
上述代码从A4中取得报表需要的字段,其中SellerId.Name和SellerId.Dept分别表示emp表中的员工名字和部门名称,运算符“:”表示重命名。A5的计算结果如下:
到此为止,报表需要的数据就全部计算出来了。最后只需用result A5将A5中的二维表返回报表工具。集算器对外提供JDBC接口,报表工具会将集算器识别为普通数据库,集成方案请参考相关文档。
接下来以JasperReport为例设计一张简单报表,表样如下:
需要定义两个报表参数pdays、pdeps,分别对应集算器中的两个参数。预览后可以看到报表结果:
报表调用集算器的方法和调用存储过程一样,比如将本脚本保存为afterjoin1.dfx,则在JasperReport的SQL设计器中可以用afterJoin1 $P{pdays},$P{pdepts}来调用。
有了esProc的协助,报表工具还可以处理更复杂的多数据源join后计算。比如:找到某日期之后每个销售员的销售额增长最快的三天,展现销售员名字、这三天的日期、销售额、增长率。
集算器代码:
A1=myDB1.query("select * from sales where OrderDate>=?",beginDate)
上述代码用来查询表sales中某日期之后的订单,其中beginDate为报表传来的参数,假设该值为”2015-01-01”,则A1的计算结果如下:
A2=myDB2.query("select * from emp")
上述代码查询emp表,结果如下:
A3=A1.switch(SellerId,A2:EId)
上述代码将A1中的SellerId字段替换成A2中对应的记录,结果如下:
A4=A3.group(SellerId)
上述代码将订单按SellerId分组。下图左侧是A4的计算结果,右侧是其中两个SellerId的订单。
A5=A4.(~.groups(OrderDate,SellerId;sum(Amount):subtotal))
上述代码将每个SellerId的订单再按照OrderDate和SellerId分组,并汇总各组的订单金额,即:每个销售员每天的销售额。如下图:
上述代码中“A4.()”表示对A4的每个成员进行循环计算,括号中的“~”是成员变量,即某SellerId对应的订单记录。“~.groups()”表示对每个成员应用函数groups。函数groups可对数据分组并进行简单的汇总,函数group可以只分组不汇总。
A6=A5.(~.derive((subtotal-subtotal[-1])/subtotal[-1]:rate))
上述代码计算出每个销售员销售额的日增长率,计算结果如下:
上述代码中,函数derive用来增加新字段,字段名为rate,算法为“(当日销售额-上一日的销售额)/上一日的销售额”。可以看到,集算器用subtotal[-1]来表示上一日的销售额,可以轻松进行相对位置的计算。
值得注意的是,由于第一条记录没有对应的“上一日的销售额”,因此销售额增长率为Null。
A7=A6.(~.select(#!=1))
这句代码在A6的基础上去掉每组数据的第一条记录(因为第一条记录的增长率为无意义的Null)。
代码中的函数select可以进行查询,“#”表示循环序号,“#!=1”即序号不等于1。同样的功能也可以用函数delete来实现,但性能稍低,这是因为函数select只返回引用,而delete需要改变实际数据。
A8=A7.(~.top(-rate;3))
上述代码可以计算出每个销售员销售额增长率最大的三天对应的记录。函数Top可以根据某字段(或某几个字段的表达式)取出前N条记录。计算结果如下:
A9=A8.union()
上述代码将A8中的各组数据合并起来,形成新的二维表A9,如下:
A10=A9.new(SellerId.Name:Name,OrderDate,subtotal,rate)
上述代码从A9中取出需要的字段,即本案例最终计算结果。
result A10
上述代码将A10中的二维表返回报表工具。
相关推荐
此外,对于PB的其他高级特性,如DataWindow的动态加载、多数据源绑定等,源码也是一个很好的学习资源。 在实际项目中,自定义报表生成源码的优化和维护也是关键。随着业务需求的变化,可能需要不断调整和改进报表...
水晶报表是一款功能丰富的报表设计工具,支持多种数据源,如SQL Server、Oracle、MySQL等,能够帮助用户创建各种复杂的报表格式,包括表格、图表、交叉表、地图等。通过其直观的拖放界面和强大的数据处理能力,用户...
业务查询是IUFO系统的一项重要功能,它可以帮助用户从多个数据源中提取所需数据,以便于进一步分析和展示。在构建应收账款明细表的过程中,业务查询主要用于从NC数据库中获取客户的档案信息和其他相关数据。 ##### ...
-- 通常报表数据源来自于各业务单据,采用一个UNION ALL来把所需的字段内码拿出来 SELECT u1.fbillno, N'生产入库单' AS FBillName, u1.fbilltype AS fbilltypeid, u1.fstockorgid, u1.fprdorgid, 0 AS ...
合并方案表iufo_hbscheme记录了报表的合并方案名称和数据版本号,这在处理多维度、跨数据源的数据合并时非常关键。 生成带有浮动行的企业报表时,SQL脚本的编写步骤如下: 1. 确定指标数据表IUFO_MEASURE_DATA_X,...
这些工具提供了图形化设计界面,可以方便地创建复杂的报表布局,并支持多种数据源,如数据库、XML、CSV等。 JasperReports是一个广泛使用的开源报表库,它允许开发者通过简单的API或XML模板来设计报表。通过IReport...
UReport报表文件通常以`.ureport.xml`为扩展名,它们是报表设计的载体,包含了报表布局、样式、数据源和计算逻辑等信息。例如,压缩包中的`contractProtocol_tgr.ureport.xml`、`contractProtocol_hbjm.ureport.xml`...
报表是对数据的结构化展示,它可能来源于不同的数据库、电子表格或其他数据源。当两张报表无法对齐时,可能意味着它们的列名不一致、行数不同步、数据类型不匹配,或者是时间范围、单位或精度存在差异。解决这类问题...
SSRS(SQL Server Reporting Services)是微软提供的一款强大的报表服务工具,它允许用户创建、管理和部署各种复杂的报表。在SSRS中,分组(Group)功能是实现数据组织和汇总的关键特性,尤其在处理具有层级关系的数据...
- **数据源确定**: 确定报表所需的数据来源。 ##### 2. 设计报表结构 - **布局规划**: 规划报表的整体布局。 - **组件选择**: 根据需求选择合适的报表组件。 ##### 3. 编写查询逻辑 - **SQL编写**: 根据需求编写...
- 多数据源报表:结合多个数据库或其他数据源生成复杂报表。 - 图形报表:使用内置的JFreeChart库创建各种图表。 通过这份jasperReport笔记,你可以了解到jasperReport的各个方面,从基础概念到高级特性的应用,...
阿里大数据计算服务MaxCompute是阿里巴巴云推出的一款强大的大数据处理平台,它为企业提供了高效、稳定、易用的大规模数据处理能力。在流式计算方面,MaxCompute引入了Stream SQL,这是一项完全托管的分布式数据流式...
总的来说,Grafana的transformation功能极大地扩展了其在报表生成上的灵活性,使用户能够在不支持复杂查询的数据源上也能创建出丰富的统计报表。通过巧妙地组合和配置transformation,用户可以根据实际需求自定义...
- **JOIN 使用**: 学习如何通过 JOIN 功能整合不同数据源,以实现更全面的数据分析。 - **上钻/下钻**: 支持用户根据需要深入查看数据细节或概括查看整体情况。 - **分类汇总**: 实现基于特定分类的汇总计算,例如按...
2. **数据源支持**:不仅支持关系型数据库,还支持XML、CSV、JSON等多种数据源,提供灵活的数据获取方式。 3. **脚本语言支持**:除了Java,还支持Groovy和JavaScript,使得用户可以编写更复杂的计算和逻辑。 4. **...
1. **数据接入**:通过配置数据源,将实时数据流接入到流计算系统,例如来自Web API、IoT设备或其他系统的数据流。 2. **数据处理**:利用流计算SQL进行数据清洗、过滤、聚合等操作,如示例中的固定时间窗口下的单词...
**多重查询**则允许在一个报表中集成来自多个数据源的信息。通过数据链接,可以合并不同数据库表的数据,或者结合不同查询的结果,以实现更复杂的数据分析和展示。这种能力使得Oracle Developer Reports能处理更丰富...
在安卓(Android)平台上开发应用时,有时候我们需要处理复杂的数据展示,例如多维报表。多维报表能够提供更深入的数据洞察,帮助用户更好地理解和分析数据。这个“安卓Android源码——安卓Android多维报表.rar”...
Flink的易用性也得到了提升,支持写HDFS并兼容LZO压缩,自动处理数据源中的换行,还支持第三方依赖JAR的分发。流式SQL的引入降低了开发门槛,提供了稳定的语法和自动优化功能,使得批流处理可以统一进行,满足了数仓...
4. **数据连接**:VF可以与其他数据源(如ODBC、OLE DB)进行数据交换,实现多数据源的数据集成。 5. **网络和Internet功能**:VF支持Web应用开发,可以创建CGI(通用网关接口)应用程序,与Web服务器交互,实现Web...