天天看点

解决报表中的复杂运算

报表工具擅长统计图和表格的设计、风格美化、查询界面、录入填报、导出打印,是应用最广泛的工具之一。而报表中经常存在着复杂运算,对报表设计者的技术能力提出了很高的要求,是报表设计最大的障碍之一。

某公司有一张HighGrowth SalesMan of the Year报表,主要通过销售数据来分析连续三个月销售额增长超过10%的销售人员,展示他们的销售额amount,销售额环比Amount LRR,客户数量Client Count,客户数量环比Client LRR等指标。报表式样如下图:

解决报表中的复杂运算

报表的主要的数据源是每月销售数据sales表,它存贮着销售人员每个月的销售情况,以salesMan和month为主键。结构如下图:

解决报表中的复杂运算

可以看出,计算连续三个月销售额增长超过10%的销售人员名单,是这份报表最复杂的部分,只要计算出这个名单,那么剩下的部分都可以轻易地利用报表工具呈现出来。让我们看一下用SQL和集算器是如何计算的。

用SQL语句解答

01 WITH A AS

02       (SELECT salesMan,month,amount/lag(amount) 

03          OVER(PARTITION BY salesMan ORDER BY month)-1 rising_range 

04           FROM sales), 

05      B AS

06            (SELECTsalesMan, 

07                CASE WHEN rising_range>=1.1 AND

08                    lag(rising_range) OVER(PARTITION BY salesMan

09                          ORDER BY month)>=1.1 AND

10                    lag(rising_range,2) OVER(PARTITION BY salesMan

11                          ORDER BY month)>=1.1 

12               THEN 1 ELSE 0 END is_three_consecutive_month 

13      FROM A) 

14 SELECT DISTINCT salesMan FROM B WHERE is_three_consecutive_month=1

1、1-4行:使用SQL-2003的窗口函数求得每个销售人员每个月的销售额环比rising_range,其中lag是求相对的上个月销售额,这里用WITH语句生成了一个独立子查询。

2、5-13行:继续使用窗口函数,求得每条记录中销售人员的连续增长标志is_three_consecutive_month_gains,其中邻近三个月的rising_range同时大于1.1的销售人员,这个标志为1;否则等于0,这里用到了case when的技巧。最后仍然使用”WITH”语句生成独立子查询B。

3、14行:依据上两步的结果,求得符合报表条件的销售人员,即is_three_consecutive_month_gains等于1的记录。这里需要用distinct过滤掉重复的销售人员。

集算器的解决

解决报表中的复杂运算

A1:按销售人员对数据分组。每组是一个销售人员的所有数据,按月份从小到大排序。

A2:引用上一步的计算结果,选出A1中符合条件的组。条件来自A1运算区域中的最后一个格,即B3格。B2和B3都属于A1的运算区域。把条件分步写在多个格里可以降低难度。

B3:条件判断。如果组内连续3个月环比大于1.1,则这组数据满足条件。这里amount[-1]是对于当前数据的上一条数据,amount/ amount[-1]既环比。pselect用来获得组内序号,遇到组内第一条符合条件的数据时,pselect就立即返回序号不再重复计算。

A4:获得A2中销售人员的编号,这个结果将以JDBC的形式返回给报表工具使用。

这个例子按照”分步骤”计算的方法会很清晰,比较适合用存储过程,但报表开发人员往往不能随意在数据库中添加存储过程,所以一般还是需要使用SQL语句来解决。普通的SQL-92语句解决此类问题将会非常费力,这里采用尚未广泛使用的SQL-2003标准,可以降低难度。即使这样,仍然需要面对大段难懂的SQL,对普通报表开发人员而言,这无疑是个巨大的挑战。

集算器解决此类计算则更为敏捷轻松。它使用类似Excel的网格风格来书写表达式,天然分步;单元格可以互相引用计算结果,省去了复杂的嵌套查询,也无需定义杂乱的变量;集算器还提供了相对位置、序号引用、分组后分步计算等针对批量数据计算的功能,可以极大的简化计算步骤。