Oracle Essbase入门系列(三)
数据库计算
Essbase中单元格的数据可以是外部输入或计算而得,单元格因而分为输入单元格和计算单元格。计算单元格的计算方法可以通过大纲中维度成员的合并计算符和公式脚本定义,此称为大纲计算定义。
例1:张大明家在上海市区和浦东各有一套房,1月5日时张大明收到市区房子的水费和电费账单,然后缴付;张大明的妻子王翠花同时也收到并缴付了浦东房子的账单。两地的水电单价和用量均不一样。
在HomeFinancial应用程序中,对应的单元格录入数据如下表的数据。表中,灰底的单元格是输入单元格,其中的数据是手工录入;而公共事业费,作为父级成员应由其子代成员作合并计算,所以对应表中黑底的单元格就是计算单元格。

Essbase中子代成员合并到父级成员的计算可以通过合并计算符设置。在维库编辑HomeFinancial应用程序。选中维度结构中任何非1代成员,都有一项【Consolidation】属性,这就是合并计算符。双击此属性进行编辑,如下图,在下拉列表中有7种合并计算符供选择,下表列出了这些计算符的含义。创建成员时,默认的合并计算符是加法“+”。


在例1中,公共事业费需要按如下公式进行合并:
公共事业费 = 电单价 × 电用量 + 水单价 × 水用量
那么是否将公共事业费子成员的合并计算符改成下图设置就够了呢?图中成员名称后是合并计算符。

此思路是对的,但做法在Essbase中行不通。原因是Essbase中同级成员并非按数学中先乘除后加减的顺序计算,而是单纯按照成员排序顺序计算。如果按图中那样,公共事业费的计算就变成了:
公共事业费 = (电单价 × 电用量 + 水单价) × 水用量
要纠正这个错误有两种方法。其一是在维度结构上做文章,按下图重新设计维度结构,得到正确的计算顺序如下:

第二种方法是使用成员公式。通过成员公式可以编写脚本定义计算,成员公式会覆盖子代成员的合并计算。而且Essbase提供了丰富的计算函数和完善的脚本语法,在成员公式中能实现各种复杂的计算。
在维度结构中选择公共事业费成员,修改它的【Member Formula(BSO)】属性,在公式编辑器中输入脚本:
= "水单价" * "水用量" + "电单价" * "电用量";

如果要编写复杂的脚本,推荐使用EAS Console。EAS Console中的公式编辑器更强大,可以提示计算函数和运算符,可以帮助验证脚本语法。Essbase的计算函数和语法可参看官方手册。

有了成员公式,子代成员的合并计算符就没有意义了。出于严谨性考虑,可以将子代成员的合并计算符设为“~”,即子成员不参与合并计算。

回到例1最初的那个表格,横轴和纵轴分别是两个维度,仔细观察表中的计算单元格,会发现存在两个疑问。
第一个疑问,表中两个维度,代表了两种计算方向,这两种方向的计算结果是不一致的。具体来说,最右下角的单元格,代表的是整个家庭公共事业费的合计。如按箭头方向①,即沿Account维度计算,根据成员公式,结果是584.5;反之,按箭头方向②,即沿Home维度计算,根据合并计算符,结果是300.5。

显然第二种计算方向是正确的,那么如何让Essbase按我们希望的方式计算呢?答案是控制Essbase的计算顺序。就是要先计算Account维度,得到表中最下面一行单元格的数据,然后计算Home维度,得到表中最右边一列单元格的数据。后计算的结果会覆盖前面计算的结果,即是说会以300.5作为右下角单元格的最终计算结果。Essbase根据如下条件判断维度间的计算顺序。
- 如果大纲中同时包含Account和Time两种类型的维度,且Account维中使用到成员公式,计算顺序为:
- Account维度
- Time维度
- 密集维度,根据在大纲中排序计算
- 稀疏维度,根据在大纲中排序计算
- 其他情况下,计算顺序为:
- 密集维度,根据在大纲中排序计算
- 稀疏维度,根据在大纲中排序计算
因此,维度的存储类型和在大纲中的排序是控制计算顺序的两个重要手段。如HomeFinancial按照Account > Year > Home > Scenario的顺序计算,这样就能保证产生正确的计算结果。如果不清楚数据的计算顺序,可以在执行计算命令后,从Essbase的日志文件中查看。
此外,若要改变维度中个别成员的计算顺序。比如需要公共事业费在Home维度后计算,即需要表格右下角单元格的计算结果是584.5。那么可以启用公共事业费的【Two Pass Calculation】属性。此属性表明成员需要二次计算,Essbase会在按正常顺序计算一遍后,再用公共事业费的成员公式对相关单元格进行第二次计算。
第二个疑问,是电单价和水单价。按Home维度上的计算方法,使用加分“+”做合并计算,计算结果在父级成员上是无意义的。我们已经将电单价和水单价的合并计算符置为“~”,使之不在Account维度上进行合并计算,那么如何让它们不在其他维度上进行合并呢?实际上,这里想要说明的是合并计算符“~”与“^”的区别,因为这两个计算符常让人困惑和混淆。这个例子中,要让电单价和水单价在Home、Year、Scenario上都不执行合并计算,需要将合并计算符设成“^”,如下图。

改成“^”后,电单价和水单价相关单元格在计算过程中不会产生任何合并计算值。只有使用公式脚本或输入值才能向这些单元格写入数据。

除了记录日常收支流水外,我们还要为HomeFinancial加入计算现余额的功能。因此在Account维度的现金流层次下加入了4个成员。
- 期初现金:某一时期开始的现金量;
- 净收入:总收入减总支出;
- 调整:当发现收支跟现金余额对不上时,用于调整;
- 期末现金:某一时期最后的现金量;
例2:下表记录的是张大明在2013年Q1季度的现金流。

在1月1日时张大明有现金500000元,整个1月份他花了10000元,赚了30000元,则净收入有20000元。1月31日结束时他应该有现金520000元,但由于漏记,或者银行交易产生的手续费,张大明发现实际的金额是519980元,于是补录了20元的调整项。所以有如下等式:
净收入 = 收入 – 支出
期末现金 = 期初现金 + 净收入 + 调整
要在Essbase中实现净收入和期末现金的计算,可以使用成员公式。在维库中编辑净收入的成员公式属性,输入脚本:
= "收入" - "支出";
编辑期末现金的成员公式属性,输入脚本:
= "期初现金" + "净收入" + "调整";
到1月结束时张大明所拥有的现金,同时也就是2月最初所拥有的现金。于是又有如下等式:
期初现金 = 上期的期末现金
将期初现金的成员公式修改为:
IF(NOT @ISMBR("1月1日"))
"期初现金"=@PRIOR("期末现金",1);
ENDIF;
此脚本要求我们在1月1日输入期初现金,之后每一时期的期初现金都等于上一时期的期末现金。
定义了3个成员的公式后,接着要讨论一下这3个成员的计算顺序问题。前面我们使用例1来说明维度间的计算顺序,即同一类型的维度,计算顺序是由它们在大纲中的排序顺序决定的。这一规则也同样适用于同一维度中成员间的计算顺序。在同一维度的成员间,Essbase按照由低级到高级,由前到后的顺序计算。所以现金流这部分成员的计算顺序如下图。

下表用箭头标示了单元格的计算路径。

按照这样的计算路径,期初现金的成员公式会引用到晚于它计算的期末现金,从而产生错误的计算结果。例如当计算2月的期初现金时,1月的期末现金还未计算,结果得到空值。

将引用成员置于被引用成员之前,造成计算顺序错误的现象称为“前置引用”。要解决此问题,方法是让期末现金和期初现金一起计算,修改期初现金的公式脚本为:
IF(NOT @ISMBR("1月1日"))
"期初现金"=@PRIOR("期末现金",1);
ENDIF;
"净收入" = "收入" - "支出";
"期末现金" = "期初现金" + "净收入" + "调整";
然后移除净收入和期末现金的成员公式。依此计算公式,当1月期初现金计算时,1月的净收入和期末现金同时被计算。那么在计算2月期初现金时,就可以得到正确的计算结果。
接着计算2月和3月的现金流。在Q1季度,期初现金应该是1月的期初现金,期末现金应该是3月份的期末现金,净收入和调整是3个月的合计。同理,整个2013年,期初现金是Q1的期初现金,期末现金是Q4的期末现金,净收入和调整是4个季度的合计。
可见,期初现金和期末现金在Year维度上采用了一种特殊的合并方式——分别取第一个子成员值和最后一个子成员值。在现实应用场景中,常常会碰到与时间相关的计算,如同比、环比、累计等。Essbase提供了大量有关Time类型维的计算函数和方法。本例中,除了使用成员公式,可以使用时间平衡(Time Balance)计算实现期初和期末计算。时间平衡计算要求数据库中必须含有Time类型维度,且仅能用在Account类型维度上使用。时间平衡计算不会影响Time类型外其他维度的合并方式。时间平衡有3种计算,含义如下表。

在维库中,将期初现金的【Time Balance】属性设为First;将期末现金的【Time Balance】属性设为Last。
时间平衡计算还有一个属性【Skip Value】,此属性控制是否要忽略空值Missing或零值。比如现金流是从2月开始,1月的期初现金是空值。如果期初现金的【Skip Value】属性是None,不忽略空值和零值,则Q1的期初现金会是1月的空值;如果是Missing,则计算Q1的期初现金时会忽略1月的空值,取2月的值。

在有了大纲计算后,每次录入和修改数据,Essbase是不会自动按合并计算符和成员公式进行计算的。必须执行计算命令,Essbase才会计算相关单元格。计算命令可写在计算脚本中,计算脚本可精确控制计算范围和顺序,还可覆盖大纲计算。可以为数据库创建多个计算脚本,执行不同的计算脚本以实现不同的计算。每个数据库都有一个默认计算脚本。
在EAS Console中,右击HomeFinancial下的y2013数据库,菜单中选择【设置】>【默认计算】。可看到在默认计算脚本中,使用了CALC ALL语句计算整个数据库,根据需要我们可以修改默认计算脚本。要创建新的计算脚本,在y2013数据库的右键菜单中选【创建】>【计算脚本】。

执行计算脚本的途径有多种,如通过MaxL Shell,Smart View,EAS Console等。要在EAS Console中执行计算脚本,通过右键菜单选【执行计算】,然后选需要执行的脚本。

Oracle Essbase入门系列(三)的更多相关文章
- Oracle Essbase入门系列(二)
本篇开始会一个三口之家的家庭财务数据库为例,讲述Essbase的功能和开发.为了说明EPM应用程序的管理和开发过程,会绕一些弯路,不使用EAS,而尽量用EPMA. 创建应用程序 首先登陆到Worksp ...
- Oracle Essbase入门系列(一)
1. 开篇序 本文是几年前做Hyperion Planning项目时写的,后来陆陆续续有些补充.本来打算将整个EPM写一系列的教程,但HFM写到1/3就没动力了.不过至少Essbase这部分是完整的. ...
- Oracle Essbase入门系列(四)
成员存储类型 除了大纲计算,维度成员的另一项重要属性是存储类型,存储类型决定维度成员相关单元格的物理存储方式.在维库中编辑成员的[Data Storage]属性,下拉菜单中可选的5种,再加上Share ...
- mybatis入门系列三之类型转换器
mybatis入门系列三之类型转换器 类型转换器介绍 mybatis作为一个ORM框架,要求java中的对象与数据库中的表记录应该对应 因此java类名-数据库表名,java类属性名-数据库表字段名, ...
- 6. oracle学习入门系列之六 模式
oracle学习入门系列之六 模式 上篇咱们学习记录了ORACLE数据库中的数据库结构.内存结构和进程等.篇幅 蛤蟆感觉偏多了.这次要休整下,每次笔记不宜太多,不然与书籍有何差别. 我们要保证的是每次 ...
- C# 互操作性入门系列(三):平台调用中的数据封送处理
好文章搬用工模式启动ing ..... { 文章中已经包含了原文链接 就不再次粘贴了 言明 改文章是一个系列,但只收录了2篇,原因是 够用了 } --------------------------- ...
- [转]C# 互操作性入门系列(三):平台调用中的数据封送处理
参考网址:https://www.cnblogs.com/FongLuo/p/4512738.html C#互操作系列文章: C# 互操作性入门系列(一):C#中互操作性介绍 C# 互操作性入门系列( ...
- [转]oracle学习入门系列之五内存结构、数据库结构、进程
原文地址:http://www.2cto.com/database/201505/399285.html 1 Oracle数据库结构 关于这个话题,网上一搜绝对一大把,更别提书籍上出现的了,还有很多大 ...
- ActiveMQ入门系列三:发布/订阅模式
在上一篇<ActiveMQ入门系列二:入门代码实例(点对点模式)>中提到了ActiveMQ中的两种模式:点对点模式(PTP)和发布/订阅模式(Pub & Sub),详细介绍了点对点 ...
随机推荐
- css3的学习笔记1
一. 边框 1. border-color border-color是设置边框的颜色.包括border-top-color,border-left-color,border-right-colo ...
- java经典50编程题
菲波拉契数列:有一对兔子,从出生后第 3 个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? package com.day2; public ...
- 今天在Mac机器上使用了Flex Builder编辑了一个源代码文件,保存后使用vim命令去打开时发现系统自动在每一行的结尾添加了^M符号,其实^M在Linux/Unix中是非常常见的,也就是我们在Win中见过的/r回车符号。由于编辑软件的编码问题,某些IDE的编辑器在编辑完文件之后会自动加上这个^M符号。看起来对我们的源代码没有任何影响,其实并不然,当我们把源代码文件Check In到svn之类
今天在Mac机器上使用了Flex Builder编辑了一个源代码文件,保存后使用vim命令去打开时发现系统自动在每一行的结尾添加了^M符号,其实^M在Linux/Unix中是非常常见的,也就是我们在W ...
- log-malloc2 0.2.4 发布
log-malloc2 0.2.4 发布了,该版本修复了日志格式输出的 bug. og-malloc2 是一个 malloc 日志预加载库,用于检测内存泄漏问题.
- 【转载】php中iconv函数使用方法
原文:http://www.phpweblog.net/star65225692/archive/2011/03/23/7524.html 在选择用什么工具开发,唯一的指导标准就是:用最少的人 ...
- [JS6] 通过用户事件事件执行脚本
<html> <head> <title>通过用户事件事件执行脚本</title> <SCRIPT TYPE="text/JavaScr ...
- tomcat安全配置
1. 注释或删除 tomcat-users.xml 所有用户权限,看上去如下: <tomcat-users></tomcat-users> 2. 隐藏tomcat版本信息 1 ...
- JProfiler使用详细教程学习笔记
JProfiler学习笔记 推荐文章:JProfiler 入门教程 一.安装JProfiler 从http://www.ej-technologies.com/下载5.1.2并申请 ...
- MySQL笔记汇总
[目录] MySQL笔记汇总 一.mysql简介 数据简介 结构化查询语言 二.mysql命令行操作 三.数据库(表)更改 表相关 字段相关 索引相关 表引擎操作 四.数据库类型 数字型 字符串型 日 ...
- 每天一个linux命令(4):mkdir命令
linux mkdir 命令用来创建指定的名称的目录,要求创建目录的用户在当前目录中具有写权限,并且指定的目录名不能是当前目录中已有的目录. 1.命令格式: mkdir [选项] 目录... 2.命令 ...