制作统计报表,往往不是一个sql语句能搞定的。
l 有些报表需要从多个数据库取数;
l 有些虽然是从一个数据库取数,但数据是分散在数据库的很多表中,需要多个sql语句组织有关数据,然后按照某些关系归并在一起;
l 有些报表虽然是一个基础表,但对该表中的数据要经过不同的加工,一句sql语句不能将所有的报表要展现的数据组织完毕。
比如统计报表中常见的本期、累计、完成比例。在数据库中,基础数据是按照一天天的发生数存在表中,本期为月初到查询日期的累计发生数数,累计为从年初到查询日期的累计发生数,完成比例为累计除上计划数,计划数肯定要在另一个表中单独存放。本期和累计虽然都是一个表,很明显因为条件的不同,一句sql不可能做到同时取出本期和累计。这样的统计报表最少需要3个sql取数才能将报表上所需要的数据全部取出,然后按照特定的条件(比如按机构)将三个数据集的归并,之后才能展现出正确的报表。
传统的报表工具(如水晶为代表的国外报表工具),都是以单一数据集为基础的报表生成工具,如果你需要用到很多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) |
内部参数 |
这样,一个简单的统计报表就完成了。如果我们使用水晶报表,多数据集的归并,则必须要通过存储过程等方式将数据组织到一起,工作量和本软件制作同一报表相比是天壤之别。