报表模式化开发手册
(,
for
NC-V3)
朱俊彬、赖宏伟、李媛媛 NC-UAP
目 录
第一章 总体介绍....................................................................................................................... 2 1. 开发概述 ............................................................................................................. 2
技术型报表与业务型报表 ........................................................................................... 2
一般报表开发存在的问题 ........................................................................................... 2
模式化报表开发思路 ................................................................................................... 2
2. 应用模型 ............................................................................................................. 3
数据模型与展现模型 ................................................................................................... 3
数据字典 ....................................................................................................................... 4
业务系统集成 ............................................................................................................... 5
第二章 低开发难度报表........................................................................................................... 6 1. 概述 ..................................................................................................................... 6 2. 查询类报表 ......................................................................................................... 8
明细报表 ....................................................................................................................... 8
汇总报表 ..................................................................................................................... 17
列结构依赖于查询条件的报表(动态SQL )
.......................................................... 23
3. 交叉类报表 ....................................................................................................... 30
列向拼接查询型报表(复合查询)
.........................................................................
31
列向分支统计型报表( CASE-WHEN )
................................................................... 36
动态行列交叉型报表(旋转交叉)
......................................................................... 40
4. 投影类报表 ....................................................................................................... 45
单元格依赖于行列条件的报表(投影交叉)
......................................................... 45
半录入半嵌入型报表(合并查询)
......................................................................... 51
5. 算法类报表 ....................................................................................................... 55
数据加工预备知识 ..................................................................................................... 55
非投影类占比报表(普通占比)
............................................................................. 60
投影类占比报表(投影占比)
................................................................................. 65
程序送数型报表 ......................................................................................................... 69
6. 高级应用 ........................................................................................................... 73
支持穿透的非投影交叉类报表(普通穿透)
......................................................... 73
支持穿透的投影交叉类报表(投影穿透)
............................................................. 79
支持主从连动的报表 ................................................................................................. 84
支持统计图表的报表 ................................................................................................. 88
第三章 高开发难度报表......................................................................................................... 92 1. 基于行业报表工具开发的报表 ....................................................................... 92
标准报表 ..................................................................................................................... 92
分块填充报表 ...........................................................................
................................ 104
2. 基于CELL REPORT工具开发的报表........................................................... 111
CELL REPORT 工具介绍
......................................................................................... 111
CELL REPORT 报表
................................................................................................. 113
附录............................................................................................................................................... 124 1.模式一览表 ...................................................................................................... 124 2.查询引擎FAQ之参数篇 .................................................................................. 125
第一章 总体介绍
1.
开发概述
技术型报表与业务型报表
我们将报表应用划分为两种类型,一类应用的侧重点在于出报表所蕴涵的技术,开发者(程 序员或实施人员)通常凭借一定的数据库和编程知识,基于库里的业务数据,做出符合用户 需求的报表展现和输出,此类应用称为技术型报表;另一类应用则着眼于整个报表生命周期 中各环节的管理(包括出表、上报、审核、汇总、发布等流程)
,即把做报表的行为当成一 项业务,对直接开发者的主要要求在于业务熟悉程度而非技术,此类应用称为业务型报表。
前者通常由专业程序员、二次开发人员或技术型实施顾问承担开发工作,早期工具如报表模 板、自定义查询等均面向此类应用,IUFO 则是后者的代表性产品。本文档作为集团平台技 术部对外发布的开发手册,主要针对对象为技术型报表。
一般报表开发存在的问题
报表属于 ERP 项目中的关键应用,通常被用户的高层领导用于企业业绩评估、辅助决策或 对外发布。据统计,在很多交付压力较大的项目当中,报表开发占有相当的比重。就目前开 发现状而言,影响报表快速交付的主要问题有以下几点:
1、 报表开发本身的复杂性高。中国式报表由于政策以及长期人工填报的原因具有极强的个 性化特点,根据业务逻辑进行数据查询、数据组织、表样展现和界面处理的每个步骤都 耗费了很高的开发代价; 2、 报表开发的复用性低。开发人员投入巨大努力完成第一批报表后,发现第二批报表依然 要从头做起,或者另一名开发人员遇到类似于第一批报表的需求,无法借鉴(甚至根本 不知道)前人的开发成果; 3、 报表开发对专业技能要求偏高。很多二次开发人员虽然不是专门搞技术的,但通常具有 一定的开发基础,而目前的二次开发平台限制了他们发挥应有的作用。
模式化报表开发思路
所谓模式化开发,包含两方面的工作:专职人员将有代表性的应用进行归纳抽象,提取出共 性的部分形成代码框架和方案,并以手册的形式对外发布;报表开发人员拿到项目需求后, 从手册上找到匹配的模式, 通过编写一些低技术含量的子类代码或进行一些机械性的工具操 作,就能够快速地完成开发工作。以往大部分的重复性劳动已经在模式的基类或者缺省实现
第 2 页
中处理,当开发人员需要体现个性化的时候,则可以通过自己对接口的特殊实现完成。
随着模式的逐步丰富,开发人员开发各类模式报表的工作量都会明显降低,同时也实现了代 码复用和知识共享,另一方面,由于开发者的工作趋于简单和机械,他们的角色就可以由低 专业技能人员所取代。从这个角度上说,模式化是解决上节所述三个问题从而真正实现报表 快速开发的有效方案。
本手册介绍了两大类 NC 报表开发模式,一类是基于查询引擎的低开发难度报表,其编码量 小,操作简单,适合于开发数据和格式比较规律的报表;另一类是基于行业报表工具的高开 发难度报表,主要工作是编写子类代码,自由度高,适合于开发复杂报表。
2.
应用模型
数据模型与展现模型
一般来说,报表是由数据和格式组成的整体。报表的数据模型通常包含以下信息:
1、 数据结构; 2、 待定参数描述; 3、 取数规则描述; 4、 数据加工算法描述; 5、 多个数据集合之间的数据关联描述;
可作为数据载体的常用 NC 数据结构包括:
1、 ——循环访问 VO,是由属性和取值成对组成的 集合,提供了根据属性获得/设置值的方法,是单据和报表模板采用的主要结构; 2、 ——普通 VO,包含多个属性及每个属性的 getter 和 setter 方法,是 业务组主要数据结构的父类; 3、 ——存储数据集,由元数据和内容数据两部分组成, 元数据(Column[])描述了各列的信息,内容数据描述了一个二维的数据集合,当游标 指向内容数据的某行时,可以获得该行指定列的数据,用于查询引擎; 4 、 — — 内 存 结 果 集 , 同 样 由 元 数 据 和 内 容 数 据 组 成 , 其 中 元 数 据(MemoryResultSetMetaData)描述各列信息,内容数据(ArrayList)描述了一个二 维数据集合,可以直接访问其任何元素,目前被一些业务算法使用; 5、 Object[][],Vector,ArrayList——这些都是 JDK 的常用结构,均可存储二维数据。
报表的展现模型通常包含以下信息:
1、 控件(核心控件是表格)属性和布局; 2、 控件显示内容与显示规则(绑定数据、参数、行列格式、界面资源等); 3、 控件连动规则; 4、 数据处理规则(定位、排序、过滤、统计、公式、交叉、钻取等); 5、 动态扩展规则; 6、 输入输出控制(待定参数设置,打印,导出等)
第 3 页
数据字典
NC 数据字典提供了统一的数据建模平台,支持对各种数据库对象进行管理,维护这些物理 对象的逻辑属性,并向外系统提供访问数据库逻辑信息的接口。以查询引擎为例,查询对象 的定义是基于数据字典进行的,而这份数据字典来自查询对象所指定的数据源。由于多数报 表的列与业务数据库的字段存在某种对应关系, 因此数据字典的存在有助于提高查询定义的 直观性和易用性。
NC 数据字典通常在安装产品时候由系统生成,如果想自己为某些数据库对象生成字典,可 以采用数据字典管理界面提供的导入方法。导入方式包括三种(详细操作可参见《数据字典 导入说明》 )
:
1、 解析 PDM 文件(xml 格式)
; 2、 解析 NC 标准建库脚本; 3、 提取数据库元数据;
如果需要给非 NC
数据库(比如用户采用的第三方数据库)生成数据字典,可以利用 PowerDesigner
提供的逆向工程功能将库里的物理表生成 PDM
文件,修改其中表和字段的 中文名称,然后以 xml 文件格式存储,再使用上述第一种方法导入。
第 4 页
业务系统集成
对于直接使用查询引擎开发出的报表,可以使用以下两种方式挂接到业务组的功能节点。强 烈建议把准备挂接节点的查询对象和格式对象的编码设为与业务系统相关的有意义字符串, 以避免不同业务系统预置对象互相覆盖的危险性。
报表管理节点挂接法:
1、 注册功能节点,类名为 ; 2、 下挂一个参数,参数名为 folderId,参数值为客户化下查询引擎管理中相关报表目 录的 ID(可从数据库表 pub_formatmodeldef 的 id 字段查出)
。
独立报表节点挂接法:
1、 注册功能节点,类名为::
2、 下挂两个参数:
pkQryNode——界面模型对应的编码 (可从查询引擎管理界面读取), dsName——查询定义所在数据源。
对于高开发难度模式的报表,则与普通功能节点一样挂接 ToftPanel 的子类即可。
第 5 页
第二章 低开发难度报表
1.
概述
本手册列举的低开发难度报表模式统一由查询引擎(V3 版本)提供解决方案。查询引擎是 一个面向高级实施人员和普通开发人员的查询建模产品, 延续并完善了自定义查询体系的技 术路线,在全面支持复杂查询的设计和个性化的报表展现的同时,大幅度降低了报表开发人 员的编码工作量和专业技能要求。
我们再来看一下查询引擎的适用性和不适用性。查询引擎长期作为一个查询工具发展,因此 尤其适用于与数据库查询分析或数据挖掘关系密切的报表开发, 同时也支持程序员调用服务 器端代码对数据进行业务处理。
另一方面, 自定义查询体系与模板体系存在一个很大的不同, 模板体系在发布产品之前已经由程序员录入了大量初始化数据, 因此不同用户能够分配到不 同的查询模板、报表模板和打印模板,而自定义查询体系是完全自定义的实时开发,没有模 板的预制数据,因此在一个时刻只支持一种参数控制样式、一种报表界面样式和一种打印样 式(或直接打印)
,但这些样式均可在设计态修改。在展现上,由于查询引擎使用的是 SWING 的表格控件,因此对一些 EXCEL 风格的需求支持不够,这个薄弱环节将在 V31 得到加强。
总体来说,V3 版本的查询引擎暂不适用于以下两类报表开发:
1、 有多模板分配需求的报表,或对打印有高度要求的报表; 2、 存在表体合并单元格的报表。
查询引擎的查询模型(数据模型)设计如下:
查询模型流程如下所示(设计态/运行态)
:
第 6 页
界面模型(展现模型)设计如下:
第 7 页
界面模型流程如下所示:
本章共介绍了五大类报表的十五种开发模式。尽管这些模式之间存在相当差异,但是针对以 前我们发现的一些用例杂乱导致的培训效果问题,本章的所有范例集中面向两个业务应用 (单位费用统计和部门人事统计)
,即用不同方案解决相似问题,以便于读者从中领会和比 较这些模式的原理、特点和适用性。希望这种做法不会给读者造成一个误导:查询引擎只能 解决这两类报表的应用。
2.
查询类报表
查询类报表指通过一个或多个 SQL 查询结果形成的二维数据展现出来的报表,由于 SQL 的 语法特点,此类报表通常具有固定的列结构和动态的行结构,但模式
也探讨了一种根据 参数动态改变查询列结构的方案。
明细报表
【概述】
明细报表用于展现最基本维度上的数据,即最细粒度的数据。通常明细总是相对于汇总而言 的,如果我们把某商品每个月的总销售额列表视为汇总数据,那么该商品每天的详细销售情 况就可视为明细数据;如果我们把某部门当年的总薪资情况做成汇总表,那么该部门每位员 工当年的薪资情况就可以做成明细表。
查询类报表中的明细表通常是指一些不含聚合函数的 SQL 语句直接能够查询出的数据形成的报表。
【应用场景】
第 8 页
开发人员需要通过多表联查 SQL 或者复合查询获得表体数据,同时为报表展现提供待定条 件设置、栏位设置、排序、过滤、定位、小计合计及输出等功能。当明细表与汇总表一起出 现时,用户通常还会有从汇总数据联查明细数据的需求(又称穿透或钻取)
,此类应用将在 模式
中介绍。
【适用性和不适用性】
适用于:
明细数据的取数规则可用 SQL 描述; 不适用于:
通过行列条件统计单元取值的明细表。此类报表应遵循模式
解决;
通过程序算法构造明细数据的报表。此类报表应遵循算法类报表模式解决;
【解决方案】
取数由向导式 SQL 设计描述,查询条件由参数控制机制解决,栏目在格式设计态设定,排 序、过滤、定位、小计合计、输出等功能均内置于报表浏览态。
【开发步骤】
第一步:在查询引擎管理中建立查询对象 Q1,做向导式 SQL 设计(通常不含聚合函数 sum、 avg、count、max、min)
。对于一个 SQL 无法描述的查询,比如指定单位在指定期间内不同 科目的发生额,可以利用复合查询(基于查询对象的查询,可参考模式 )进行描述。Q1 中待定的信息由参数定义描述,普通参数可以在向导式设计的筛选条件处引用,替换型参数 可以在向导式和手工式设计的任意位置引用(参见 FAQ 文档)
;
第二步:创建格式对象 F1,引用查询对象 Q1 并嵌入表格,做相关的栏位、列格式和列表头 设计。表头表尾可放置绑定参数的控件;
第三步:浏览 F1(或挂功能节点)
,设置参数,检查数据与格式是否正确;
【FAQ】
1、如何充分发挥查询模型中参数的功能? 答:参见附录提供的《查询引擎 FAQ 之参数篇》 。
2、格式设计中的 16 种控件各有何种用途? 答:表格、图表是核心控件,用于绑定数据集;面板、拆分窗格(分割面板)
、多页签作为 界面容器;标签、文本框、下拉框(组合框)
、参照、文本域、复选框、单选框是表头表尾 控件,需要放在容器上面,用于绑定参数;下拉框、列表绑定枚举型参数,参照绑定参照型 参数;主子表是已经不推荐使用的连动展现控件;按钮、树暂无实际用处。
3、如何控制报表的输出格式? 答:打印输出利用格式设计中的打印设置功能控制,EXCEL 输出由界面表格的样式控制。
【范例】
单位费用明细表——各单位在指定期间范围内的费用明细情况。
报表中要求包括公司、 期间、 制单日期、科目、分录摘要、发生额等信息,用户可以根据年度和期间范围进行查询。
第 9 页
公司
期间
制单日期
科目
摘要
借发生额
贷发生额
1、 查询引擎管理主界面创建查询对象,编码为 gldetail,名称为费用明细;
2、进行参数定义,增加三个字符型参数:年,起始期间,终止期间;
3、进行 SQL 向导设计:从数据字典添加凭证表(gl_voucher)
、凭证分录(gl_detail)
、科目 表(bd_accsubj)和公司目录(bd_corp)
,指定表间连接关系、查询字段、筛选条件(先定 义确定条件)和排序字段;
第 10 页
第 11 页
4、在筛选条件页签增加待定条件,在右操作数框中按 F12 引用参数;
5、创建格式对象,编码为 gldetail,名称为“费用明细表” ;
第 12 页
6、引用查询“费用明细” ;
7、进行格式设计:添加表格和面板控件,表格停靠于中部,双击控件设置属性,绑定数据 集费用明细,面板停靠于北部(作为表头容器)
,采用流式布局(FlowLayout)
,在面板上放 三个文本框控件,分别绑定费用明细的三个参数;
第 13 页
第 14 页
8、 (可选)定义一种列格式,用于显示两位小数,在表格属性框的列格式分栏中由两个金额 列引用此列格式;
第 15 页
9、浏览费用明细表(先设置参数)
;
第 16 页
汇总报表
【概述】
汇总数据通常与明细数据相对, 是指在明细数据基础上指定若干个有分类意义的字符型列进 行分组,并对另外若干个有统计意义的数值型列进行求和(或求平均、最值、计数等)获得 的数据。展现汇总数据的报表称为汇总报表。
【应用场景】
我们再细分为两种应用:
1. 静态汇总设置:
查询数据的 SQL
中指定了分组列和汇总列,此设置在报表浏览状态不再改变。要求提 供待定条件设置、栏位设置、排序、过滤、定位、小计合计及输出等功能。
2. 动态汇总设置:
事先对数据设定某种缺省的汇总设置,此设置在浏览态可做更改,并重新计算汇总数据。
同时具备上述功能需求。
【适用性和不适用性】
适用于:
汇总数据的取数规则可用 SQL 描述; 不适用于:
通过行列条件统计单元取值的汇总表。此类报表应遵循模式
解决;
通过程序算法构造汇总数据的报表。此类报表应遵循算法类报表模式解决;
【解决方案】
取数由向导式 SQL 设计描述,查询条件由参数控制机制解决,栏目在格式设计态设定,动 态汇总由旋转交叉机制解决,排序、过滤、定位、小计、输出等功能均内置于报表浏览态。
【开发步骤】
1、静态汇总设置 第一步:在查询引擎管理中建立查询对象 Q2,做向导式 SQL
设计,定义带有聚合函数的 SQL 语句。单个 SQL 无法描述的查询利用复合查询描述。在 Q2 的查询模型中创建参数和 引用参数,用来描述待定的信息;
第二步:创建格式对象 F2,引用查询对象 Q2 并嵌入表格,做相关的栏位、列格式和列表头 设计。表头表尾可放置绑定参数的控件;
第三步:浏览 F2(或挂功能节点)
,设置参数,检查数据与格式是否正确;
2、动态汇总设置 第一步:同上述第一步(但也可以不设置聚合函数,而是在旋转交叉设置中把缺省的分组列 放到行列表中,把缺省的汇总列放到值列表中)
;
第二步:同上述第二步,因交叉表的列结构不能在设计态确定,因此只能指定非汇总列的列 格式等信息;
第 17 页
第三步:同上述第三步,需要改变汇总设置的时候,利用表头右键菜单的交叉功能把新的汇 总列移到交叉行列表,确定即可; (关于交叉的详细说明参见下一节)
【FAQ】
1、 行 SQL 向导设计时如何指定 group by 字段? 答:无需指定,系统自动把不含聚合函数的查询字段作为 group by 字段。
2、 行 SQL 手工设计时为何 order by 字段无效? 答:需要显式指定排序字段的排序方式(升序——asc,降序——desc)
。
【范例】
单位费用汇总表——各单位在指定期间范围内的费用汇总情况。
报表中要求包括公司、 期间、 科目、汇总发生额等信息,用户可以根据年度和期间范围进行查询。
公司
期间
科目
借发生额
贷发生额
1、 创建查询对象,编码为 glsum,名称为费用汇总;
2、进行参数定义,增加三个字符型参数:年,起始期间,终止期间;
3、进行 SQL 向导设计:从数据字典添加凭证表、凭证分录、科目表和公司目录,指定表间 连接关系、查询字段、筛选条件和排序字段(除查询字段外均与模式
的范例相同)
;
第 18 页
4、在筛选条件页签增加待定条件,在右操作数框中按 F12 引用参数;
5、创建格式对象,编码为 glsum,名称为“费用汇总表” 。引用查询“费用汇总” ;
6、进行格式设计:添加表格和面板控件,表格停靠于中部,绑定数据集费用汇总,面板停 靠于北部(作为表头容器)
,采用流式布局,在面板上放三个文本框控件,分别绑定费用汇 总的三个参数;
第 19 页
7、浏览费用汇总表(先设置参数)
;
第 20 页
8、当前汇总设置是对公司、期间、科目分组统计发生额,如果需要动态改变汇总依据,则 可以使用表头右键菜单中的交叉功能。比如我们需要按照公司、期间重新汇总,则把公司和 期间移至交叉行列表,发生额移至交叉值列表,确定即可;
第 21 页
9、如果我们把科目移至交叉行,期间移至交叉列,发生额移至交叉值,那么就实现了带有 数据旋转的动态汇总,即展现各科目在不同期间下汇总出来的发生额。关于旋转交叉的详细 应用可参看模式 ;
第 22 页
列结构依赖于查询条件的报表(动态
SQL)
【概述】
我们前边提到过,SQL
查询的结果具有固定的列结构和动态的行结构,前两个模式中虽然 都引入了参数来控制动态信息,但也只用于待定的筛选条件,即影响报表的行结构。然而有 一类报表因查询条件的不同而同时具有动态的列结构和行结构, 比如在供应链的一些单据查 询报表中, 如果用户在查询条件中勾选了联查订单或到货单, 那么报表会在静态的列结构 (可 能有 10 列)后面追加一些动态的列或列分组,用于显示联查单据的明细信息(此时报表可 能就变成了 20 列)
。
【应用场景】
开发人员需要把静态的查询 SQL 同用户对查询条件设置的取值结合起来,构造出几种不同 的 SQL,分别对应于用户希望看到的各种报表展现结果。这些 SQL 不仅仅存在筛选条件的 差异,也可能存在查询字段、查询表、分组字段、排序字段的差异。由于本模式采用的技术 方案需要通过代码片段来描述查询 SQL 究竟被如何矫正,因此本模式仅建议熟悉 JAVA 编 程的报表开发人员使用。
【适用性和不适用性】
适用于:
第 23 页
查询结果可由规范的静态 SQL 和动态参数取值联合决定; 不适用于:
查询必须通过难以解析的复杂手工 SQL 才能描述;
要求对动态增加出来的列结构进行列格式设计的报表 (因为这些列在设计态是未知的);
【解决方案】
取数由向导式 SQL 设计描述,查询条件由参数控制机制解决,如何根据参数取值调整静态 SQL 则由 SQL 整理中的代码片段来描述。
SQL 整理中的常用数据结构和接口方法如下所述:
1、 查询基本定义类 QueryBaseDef,所提供方法包括:
FromTableVO[] getFromTables(); 交叉类报表
数据库当中的表往往是象下面这样存储的:
姓名
月份
销售业绩
张三
1
2000
张三
3
5000
李四
2
3000
李四
3
4000
第 30 页
但用户要求的报表往往是象下面这样的:
姓名
1
2
3
张三
2000
5000
李四
3000
4000
类似这样,把原始数据中一列(或几列,通常有分组意义)数据的不同取值维持在表的左侧 不动(比如上表中的姓名)
,把另外一列(或几列,通常有分类意义)数据的不同取值旋转 到行的方向成为列标题(比如上表中的月份)
,再把另外一列(或几列,通常有统计意义)
数据对应汇总到旋转出来的列标题下面(比如上表中的业绩)
,就形成了交叉表。
在上述过程中,我们根据交叉规则把原始数据中的列分成了三种,第一种称为交叉行(其数 据交叉后出现在行上)
,第二种称为交叉列(其数据交叉后出现在列头上)
,第三种称为交叉 值(交叉前行、列、值的数据出现在一行上,交叉后值的数据出现在行、列的交叉点上)
。
交叉报表比普通报表提出了很多新的问题,比如:数据交叉如何实现,交叉后列数目的不确 定性如何处理,列的顺序如何控制等等。根据实现方法的不同,以及能否预先确定交叉后的 列结构,本章节提供了以下三种交叉报表模式的解决方案。
列向拼接查询型报表(复合查询)
【概述】
报表在列向可以被划分成几个分组,每组由若干个列构成,每个列分组的数据能够通过 SQL 查询获得,而不同列分组的数据出现在同一行的前提是它们对应于同一个行 ID。即报表数 据可以通过多个查询结果集相互连接的方式获得。
【应用场景】
开发人员需要从某个具有分类意义的列中提取若干不同的取值,将它们旋转成为列标题,再 对另外一些有统计意义的数值列进行汇总。用户表样明确规定了这些列标题及其顺序,因此 交叉后的列结构是事先能够确定的,无论这些列是否包含有效的统计数据,它们都将在报表 中存在,因此我们称之为动态行固定列报表。
【适用性和不适用性】
适用于:
能够预先确定交叉后列结构的报表;
报表的每行数据都具有一个唯一的行 ID,该 ID 可能是某个字段或某几个字段的组合; 不适用于:
动态列结构的交叉报表; 【解决方案】
利用复合查询解决固定列结构的交叉应用,每个交叉列对应一个查询,而用于连接多个查询 的行 ID 正是交叉行字段的组合。
【开发步骤】
第 31 页
第一步:分析交叉报表的结构,找出交叉行字段、交叉列字段和交叉值字段。假定交叉列字 段有 n 个(因为是固定列结构交叉,所以 n 是定数)
;
第二步:创建 n 个查询对象分别对应于 n 个交叉列字段,通常这些对象会通过确定筛选条件 与列标题挂钩;
第三步:创建复合查询对象 Q4,通过增加临时表的方式把上述 n 个查询对象选为查询表, 这些临时表的连接条件就是交叉行字段的组合,而 Q4 的参数应该是 n 个查询对象的参数的 并集,这样才能保证 Q4 的参数设置能够分发给各个被引用查询;
第四步:创建格式对象 F4,引用查询对象 Q4 并嵌入表格,做相关的栏位、列格式和列表头 设计。表头表尾可放置绑定参数的控件;
第五步:浏览 F4(或挂功能节点)
,设置参数,检查数据与格式是否正确;
【FAQ】
1、 定义复合查询有什么注意事项? 答:首先要保证复合查询和各个子查询都使用相同的执行数据源(对于单数据源版查询引擎 无此问题)
,其次如果修改了子查询的定义要保证复合查询定义中的一致性。
【范例】
部门员工民族统计表——要求统计指定公司下各部门中不同民族的员工数, 民族预先指定为 汉族、满族和蒙古族,报表中包含部门编码、部门名称、汉族人数、满族人数和蒙古族人数。
请注意,这里作为交叉行并可以承担行 ID 角色的字段是部门信息,作为交叉列并可以承担 子查询过滤角色的字段是民族,作为交叉值的字段是人数。
部门编码
部门名称
人数
汉族
满族
蒙古族
1、 创建查询对象,编码为 han,名称为汉族,在筛选条件页签设置确定条件“民族=’汉族’” , 用于查询各部门的汉族员工人数;
第 32 页
2、 复制查询对象 han,修改编码为 man,名称为满族,修改确定条件为“民族=’满族’” , 用于查询各部门的满族员工人数;
第 33 页
3、 复制查询对象 han,修改编码为 menggu,名称为蒙古族,修改确定条件为“民族=’蒙古 族’” ,用于查询各部门的蒙古族员工人数;
4、 创建查询对象,编码为 nationalityA,名称为部门员工民族统计 A,选择表为部门档案和 上述三个查询对象对应的临时表,利用部门主键字段连接。部门档案提供部门编码和名 称信息,三个子查询分别提供三个民族的员工人数。我们之所以没有在子查询中直接查 出部门编码和名称再在复合查询中利用部门编码进行连接,是因为这样做可能导致最终 数据只列出拥有汉、满、蒙族员工的部门,而不列出全部的部门;
第 34 页
5、创建格式对象,编码为 nationalityA,名称为“部门员工民族统计表 A” ;引用查询“部 门员工民族统计 A”;
6、进行格式设计:添加表格控件,绑定数据集部门员工民族统计 A,进行列表头设计与合 计设置;
第 35 页
7、浏览报表;
列向分支统计型报表(CASE-WHEN)
【概述】
严格意义上来说,本模式与上一模式面向的是同一类报表,即预先能够确定交叉后列结构的 交叉报表,或称动态行固定列交叉表。但本模式采用了另一种解决方案——结合 SQL 的分 支函数和汇总函数,把交叉列生成的各个列分组写到一个查询当中,简化了复合查询方案需 要写多个子查询对象的工作,但要求交叉值为可汇总的数值型字段。
【应用场景】
第 36 页
同上一模式。
【适用性和不适用性】
适用于:
能够预先确定交叉后列结构的报表;
报表的每行数据都具有一个唯一的行 ID,该 ID 可能是某个字段或某几个字段的组合; 不适用于:
动态列结构的交叉报表;
交叉值不能用 SQL 汇总函数统计的报表;
【解决方案】
CASE-WHEN 函数具有以下两种语法:
1、 简单 CASE 函数:
CASE
输入表达式 WHEN
取值 1 THEN
返回表达式 1 WHEN
取值 2 THEN
返回表达式 2 ………… ELSE
返回表达式 n END 2、 CASE 搜索函数:
CASE WHEN
条件判断表达式 1 THEN
返回表达式 1 WHEN
条件判断表达式 2 THEN
返回表达式 2 ………… ELSE
返回表达式 n END
假定某张表 T 的数据如下所示:
cor name
se A 公司
韩千穗
女
A 公司
智银圣
男
A 公司
金晓光
女
A 公司
王丽娜
女
B 公司
金贤成
男
B 公司
姜希灿
女
那么执行以下 SQL 语句 SELECT corp, (CASE sex WHEN "男" THEN 1 ELSE 0 END) AS male, (CASE sex WHEN "女" THEN 1 ELSE 0 END) AS female FROM T 将获得如下结果集:
cor male
femal A 公司
0
1
A 公司
1
0
第 37 页
A 公司
0
1
A 公司
0
1
B 公司
1
0
B 公司
0
1
如果我们关注的是交叉统计结果的话,只需将上述 SQL 改造为 SELECT corp, SUM(CASE sex WHEN "男" THEN 1 ELSE 0 END) AS male, SUM(CASE sex WHEN "女" THEN 1 ELSE 0 END) AS female FROM TEM_CASE GROUP BY corp 则将查出以下结果:
cor
male
femal A 公司
1
3
B 公司
1
1
也就是说 SUM(CASE
WHEN)函数能够实现交叉统计的效果,而且一个 SQL 就能达到复合 查询方案多个 SQL 的作用。在复合查询方案中出现于各子查询的确定筛选条件,就相当于 CASE-WHEN 方案中出现在 CASE 语句中的条件判断表达式。
【开发步骤】
第一步:分析交叉报表的结构,找出交叉行字段、交叉列字段和交叉值字段。假定交叉行字 段有 m 个,交叉列字段有 n 个(因为是固定列结构交叉,所以 n 是定数)
;
第二步:创建查询对象 Q5,定义 m
个字段表达式对应交叉行字段,再定义 n
个带有 SUM(CASE WHEN)的字段表达式对应交叉列字段,其中输入表达式为交叉列字段,取值为 预先确定的交叉列字段取值,返回表达式为交叉值字段或其统计表达式,ELSE 分支返回 0;
第三步:创建格式对象 F5,引用查询对象 Q5 并嵌入表格,做相关的栏位、列格式和列表头 设计。表头表尾可放置绑定参数的控件;
第四步:浏览 F5(或挂功能节点)
,设置参数,检查数据与格式是否正确;
【FAQ】
1、 CASE WHEN 语法的条件判断表达式能否使用非等值的表达式? 答:在 SQLSERVER 下没有问题,在 ORACLE 下应利用大于等于或小于等于比较符取代大 于或小于比较符。
2、 是否有办法提高 SUM(CASE WHEN)的执行效率? 答:可考虑在 CASE-WHEN 中选择性高的字段上添加索引。
【范例】
部门员工民族统计表——要求与模式
完全相同。
1、 创建查询对象,编码为 nationalityB,名称为部门员工民族统计 B,请注意查询字段表达 式中三处 CASE-WHEN 函数的写法:
第 38 页
sum(case
when ‘汉族’ then 1 else 0 end)
(汉族人数)
sum(case
when ‘满族’ then 1 else 0 end)
(满族人数)
sum(case
when ‘蒙古族’ then 1 else 0 end)
(蒙古族人数)
2、创建格式对象,编码为 nationalityB,名称为“部门员工民族统计表 B” 。引用查询“部 门员工民族统计 B” ;
3、完全类似于上一模式做格式设计:添加表格控件,绑定数据集部门员工民族统计 B,进
第 39 页
行列表头设计与合计设置;
4、浏览报表;
动态行列交叉型报表(旋转交叉)
【概述】
与前两种交叉模式不同,本模式无法预先确定交叉后的列结构,而是根据数据完全真实地展 现交叉结果,属于动态行动态列应用。这样就存在一个设计态列格式与运行态列结构之间的 矛盾,因为设计态还没有查询数据,不可能预知运行态到底会生成哪些列,因此作为此类模 式动态体现交叉结果的代价,开发人员无法对交叉值字段对应的列做精确的格式设计。
【应用场景】
在描述清楚交叉规则(指定交叉行、交叉列、交叉值字段)之后,报表要求全动态地实现数 据交叉。多层列表头常用于辅助体现交叉的维度,且交叉规则能够在运行态重新设定。
【适用性和不适用性】
适用于:
无法预先确定交叉后列结构的报表; 不适用于:
对交叉值对应列有显示顺序等要求的报表;
第 40 页
对交叉值对应列有界面统计功能(如小计、图表等)预设置要求的报表;
【解决方案】
设计态使用查询模型 SQL 向导设计中的旋转交叉设置功能来描述初始交叉规则,运行态使 用表格表头右键菜单中的交叉功能实现再次交叉。交叉设置界面中的交叉砝码的作用是,描 述交叉值字段对应的列出现在交叉列展开后的哪个层次上。
以我们前面做过的费用汇总表为例,采用以下的交叉设置:
将得到以下的交叉结果:
如果更改交叉设置中交叉砝码的位置:
第 41 页
则将获得以下交叉结果:
【开发步骤】
第一步:分析交叉报表的结构,找出交叉行字段、交叉列字段和交叉值字段;
第二步:创建查询对象 Q6,正常定义 SQL(以获得交叉前结果集为准)
,在交叉页签的旋 转交叉设置中指定交叉行、交叉列、交叉值以及交叉砝码的位置;
第三步:创建格式对象 F6,引用查询对象 Q6 并嵌入表格;
第四步:浏览 F6(或挂功能节点)
,设置参数,检查数据与格式是否正确;
【FAQ】
1、对绑定旋转交叉数据集的表格绑定列表头是否有效? 答:无效,系统将根据交叉设置自动生成列表头。
【范例】
部门员工民族统计表——要求与模式
完全相同。
第 42 页
部门编码
部门名称
人数
民族 1
民族 2
……
民族 n
1、 创建查询对象,编码为 nationalityC,名称为部门员工民族统计 C,查询字段中按部门、 民族对人员计数,旋转交叉设置中指定部门编码、名称为交叉行,民族为交叉列,人数 为交叉值:
第 43 页
2、创建格式对象,编码为 nationalityC,名称为“部门员工民族统计表 C” 。引用查询“部 门员工民族统计 C”;
3、进行格式设计:添加表格控件,绑定数据集部门员工民族统计 C;
4、浏览报表,请注意所有民族员工的人数均列示在表格中;
第 44 页
4.
投影类报表
本手册中提到的投影类报表,就是固定行固定列的报表。所谓投影是指其每个单元格内部存 放的内容与该单元的坐标(行列位置)存在直接的关系。
单元格依赖于行列条件的报表(投影交叉)
【概述】
列条件 1
……
列条件 j
……
列条件 n
行条件 1
(1,
(1,
(1,
……
行条件 i
(i,
(i,
(i,
……
行条件 m
(m, 1)
(m,
(m, n)
本类报表具有以下特点:
1、 具有固定的行列结构:m 行,n 列。交叉结果严格遵循表样格式,其行列结构不会受查 询条件和查询数据的影响;
第 45 页
2、 每行、每列均对应一个筛选条件,而表体第 i 行第 j 列的内容可以根据 SQL 语句“select 统计函数(字段) from
表 where (行条件 i) and (列条件 j)”查出,且是个唯一的值(这里 的表可能由多张表或视图连接在一起得到)
;
在人事统计报表当中有很多此类应用, 比如列头包括各种学历结构, 行头包括各种职务序列, 那么出现在本科学历所在列和处长所在行的交叉点上的内容, 可能就是所有本科学历处长的 人数,用 SQL 语言表示就是:
select count(人员) from
人事视图 where
学历=’本科’ and
职务=’处长’ 【应用场景】
报表表样形态固定,行列顺序均不能随意更改,数据来源比较一致,表体数据由所在单元向 行、列投影得到的限制条件叠加确定。在格式设计方面,不仅对列表头,而且对行表头都有 一定的要求。
【适用性和不适用性】
适用于:
表单元数据由固定 SQL 结合行列对应的 WHERE 条件唯一决定;
多行头报表; 不适用于:
不确定行结构或不确定列结构的报表;
各列分组来自不同业务系统且不能共用一个 SQL 的报表;
【解决方案】
利用查询引擎提供的投影交叉方案,在 SQL 向导设计中定义一个不完整的查询 SQL,以及 两组 WHERE 条件,一组对应行头,一组对应列头。
前面说过,本类报表的表单元数据由以下 SQL 确定:
SQL ij = select
统计函数(字段) from
表 where (行条件i) and (列条件j) 我们把 where 前面的部分成为 SQL 主体,不难看出,一张 m 行 n 列的投影交叉表,就包含 了 m*n 个 SQL 语句,但它们全都共用一个 SQL 主体。在查询对象的 SQL 向导设计当中, 前五个页签用于描述 SQL 主体,因为每个单元格只能放一个值,所以主体部分通常只有一 个查询字段表达式,虽然这部分可能查了很多张表,但这些表大多不服务于那个孤独的查询 字段,而是服务于行列条件,最后一个页签(交叉属性)的投影交叉设置可以添加任意多的 行列筛选条件,每个条件用不带 where 的 SQL 片段描述,比如“性别=’女’”或者“1=1” 。
由上可知,SQL
主体部分和行列条件部分单独存在都是不完整的,只有它们联合起来才能 描述一组(m*n 个)完整的查询。
【开发步骤】
第一步:分析交叉报表的结构,找出行条件、列条件和对应于单元数据的统计表达式;
第二步:创建查询对象 Q7,在查询表、连接条件、查询字段、筛选条件和排序字段页签中 定义 SQL 主体,在交叉属性页签定义行条件和列条件;
第三步:创建格式对象 F7,引用查询对象 Q7 并嵌入表格,进行行列表头设计;
第 46 页
第四步:浏览 F7(或挂功能节点)
,设置参数,检查数据与格式是否正确;
【FAQ】
1、投影交叉的查询定义是否只能定义一个查询字段表达式? 答:绝大部分应用都是这样的。如果定义了 n 个查询字段,每个列条件下对应的列都将翻 n 倍,这不是非常推荐的做法。
【范例】
固定行固定列的部门民族员工统计表——要求显示指定部门指定民族的人数统计, 显示顺序 不能随便设置,格式支持存在多行头和行头小计。表样如下所示:
汉族
满族
蒙古族
直属部门
财务部
行政部
小计
开发部门
HR 产品开发部
HR 产品市场部
小计
合计
1、创建查询对象,编码为 nationalityD,名称为部门员工民族统计 D。仿照模式 (旋转 交叉)进行 SQL 设计,查询字段只保留人员计数表达式一项,交叉属性进行投影交叉设置, 根据表样指定行列 WHERE 条件;
第 47 页
2、创建格式对象,编码为 nationalityD,名称为“部门员工民族统计表 D” 。引用查询“部 门员工民族统计 D”;
3、进行格式设计:添加表格控件,绑定数据集部门员工民族统计 D,做多行头设计和小计 合计设置;
第 48 页
4、浏览报表;
第 49 页
5、运行态利用交叉设置实现行列旋转;
第 50 页
半录入半嵌入型报表(合并查询)
【概述】
经常能看到这样一类固定行列结构表样,在表的不同区域有不同的数据块(这些块之间甚至 可能没有什么联系)
,另外一些区域还放着一些人为性很强的提示性文字(可能根本无法从 数据库中查出来)
,象这样的无规律报表其实是报表开发中最难处理的。本模式采用的方案 是对解决这类报表所做的一个初步尝试, 它支持开发者把利用其它方式定义的查询嵌入到表 体的某个区域,也可以把那些无法查出的文字直接录入到需要的位置。
【应用场景】
用户报表由若干矩形区域构成,每个区域或...