制作统计报表,往往不是一个sql语句能搞定的。

l         有些报表需要从多个数据库取数;

l         有些虽然是从一个数据库取数,但数据是分散在数据库的很多表中,需要多个sql语句组织有关数据,然后按照某些关系归并在一起;

l         有些报表虽然是一个基础表,但对该表中的数据要经过不同的加工,一句sql语句不能将所有的报表要展现的数据组织完毕。

比如统计报表中常见的本期、累计、完成比例。在数据库中,基础数据是按照一天天的发生数存在表中,本期为月初到查询日期的累计发生数数,累计为从年初到查询日期的累计发生数,完成比例为累计除上计划数,计划数肯定要在另一个表中单独存放。本期和累计虽然都是一个表,很明显因为条件的不同,一句sql不可能做到同时取出本期和累计。这样的统计报表最少需要3sql取数才能将报表上所需要的数据全部取出,然后按照特定的条件(比如按机构)将三个数据集的归并,之后才能展现出正确的报表。

传统的报表工具(如水晶为代表的国外报表工具),都是以单一数据集为基础的报表生成工具,如果你需要用到很多sql才能产生出一张统计报表,那么,你必须通过建临时表,通过写存储过程等办法,将分散在数据中的数据组织到一个数据库表中,然后通过报表工具展现出来。这样的做法,也能解决中国式报表的生成问题,但报表的编写和维护量将非常大,而且报表逻辑不直观,一旦客户需要更改报表格式和逻辑,将是一件非常痛苦的事情。对于这样的报表工具而言,做报表就是写程序,报表工具沦落为最普通的展现工具。

现在国内有些报表工具也有很多号称支持多数据集,但在做这样的统计报表时,一般都是单元格将各个数据集联系起来,无论是在报表生成效率和直观易用方面,都比较差。

cellReport中,建设性的加入了关于集合的运算功能,可以对各个数据集按照指定的条件分组归并,从而极大的减低开发统计报表的难度。本报表软件的集合的运算包括:并集、交集、以及集合的减法。最常用的就是求集合的并集。

下面以northWind数据集中的订单数据,制作一张中国人常用的统计报表。本报表将会用到报表参数的计算。

数据集:

本期:SELECT [类别].[类别名称], [产品].[产品名称], Sum(CCur([订单明细].[单价]*[数量]*(1-[折扣])/100)*100) AS 产品销售额

FROM 类别 INNER JOIN (订单 INNER JOIN (产品 INNER JOIN 订单明细 ON [产品].[产品ID]=[订单明细].[产品ID]) ON [订单].[订单ID]=[订单明细].[订单ID]) ON [类别].[类别ID]=[产品].[类别ID]

WHERE ((([订单].[发货日期]) Between #month_begin_date# And #end_date#))

GROUP BY [类别].[类别名称], [产品].[产品名称]

累计:SELECT [类别].[类别名称], [产品].[产品名称], Sum(CCur([订单明细].[单价]*[数量]*(1-[折扣])/100)*100) AS 产品销售额

FROM 类别 INNER JOIN (订单 INNER JOIN (产品 INNER JOIN 订单明细 ON [产品].[产品ID]=[订单明细].[产品ID]) ON [订单].[订单ID]=[订单明细].[订单ID]) ON [类别].[类别ID]=[产品].[类别ID]

WHERE ((([订单].[发货日期]) Between #year_begin_date# And #end_date#))

GROUP BY [类别].[类别名称], [产品].[产品名称]

计划数:SELECT 类别.类别名称, 每年计划.计划数

FROM 每年计划 INNER JOIN 类别 ON 每年计划.类别id = 类别.类别ID

where 计划年=DatePart('yyyy',#end_date#)

参数定义:

参数名称

数据类型

缺省值或表达式

 

end_date

Date

1997-12-02

 

Year_begin_date

Date

=firstDayOfYear(param.end_date)

内部参数

month_begin_date

Date

=monthBegin(param.end_date)

内部参数

 

 

 

这样,一个简单的统计报表就完成了。如果我们使用水晶报表,多数据集的归并,则必须要通过存储过程等方式将数据组织到一起,工作量和本软件制作同一报表相比是天壤之别。