我们开发了湖北省的非税直报系统,开发了全省各地非税系统,积累的大量数据,如何发挥这些数据的作用呢,工作之余,研究了通过olap方法,对数据进行分析处理。我将通过一系列文章,介绍完整的实现方法。
(分析维度)
先介绍几个概念:
维度(dimession) :
和mondrian维度概念基本一致维度,维度可以理解为数据的属性。
维度有层次的概念(Hierarchy),一个维度可以有多个Hierarchy,
一个Hierarchy内有多个层级(Level),使用过程中,使用其中一个Hierarchy,我们的应用当中,一般就一个Hierarchy。
维度类型(dimession type):
在非税分析中,我们用到如下的维度:
年度、版本、组织机构、期间、项目。
版本主要分为预算版本和实际版本。
组织机构即各级财政局
期间指的事季度、月份等。
项目主要是是指非税项目(科目)
分析表单(olapform):
根据业务需要动态构建的olap分析表单;
表单可以简单的理解为分析主题,分析主题当然要进行分类,表单文件夹用来管理这些分析主题。
表单布局:(layout):
分析表单的构建,根据的事行维、列维度、页面、视点的定义,和一个分析表单相关的行、列维度等就是表单布局。
布局定义了展示给用户看的分析表格的结构。
(表单与布局)
布局里的分组,以适应表单中对行维、列维度进行分组的需要;如果不显示对行、维度进行分组,默认只有第一组;
一组当中,需要依次定义维度;
表单布局的属性包括:布局id,分析表单id,维度id,布局组、排序、是否只读等信息。
这其中布局(layout_type)类型分为:行维(2)、列维(3)、页面(1)、视点(0);
例如,我们需要根据行政区划按月度分析全省交罚收入情况,可以设置如下的行、列、页面、视点。
行维:行政区划(各地财政局)
列维:我们用期间作为维度;
页面:我们采用版本、与年度。
视点:交罚项目(科目)。
布局相关数据库表如下图:
(布局的数据库表)
分析表单维度成员:
维度成员有在分析表单中有一定顺序,分析表单维度成员必然在一个布局当中。
维度成员可能有很多,但一些维度成员间存在一定的逻辑关系,
Mdx语法中的descendants()函数,就是用于处理维度关系的,
为方便用户选择,我们把维度间的关系归纳为如下关系:
成员变量
当前成员
后代成员
后代成员(包括自身)
子代成员
子代成员(包括自身)
祖先成员
祖先成员(包括自身)
父级成员
父级成员(包括自身)
兄弟成员
兄弟成员(包括自身)
零级后代
零级后代(包括自身)
如果我们不用关系,选择分析表单维度成员的时候,就可能需要穷举所有成员。
有了关系,我们就只用保存一个维度成员及基于这个成员之上的关系,基于这2个要素,可以批量构造一批成员。
还有一类特殊的成员:变量,入同比环比的时候,需要去年同期等,这时候就应该用变量了,这里不展开描述。
完整的schemal模型:
<?xml version="1.0" encoding="UTF-8"?>
<Schema name="OlapSchema">
<Cube name="模型一" cache="true" enabled="true">
<Table name="C1_FACT" alias=""></Table>
<Dimension type="TimeDimension" foreignKey="YEAR" name="年">
<Hierarchy name="年" hasAll="true" allMemberName="年" allMemberCaption="年" primaryKey="ID" primaryKeyTable="C1_DIM_YEAR">
<Table name="C1_DIM_YEAR" alias=""></Table>
<Level name="年" table="C1_DIM_YEAR" column="YEAR" uniqueMembers="true" levelType="TimeYears"></Level>
</Hierarchy>
</Dimension>
<Dimension type="StandardDimension" foreignKey="PERIOD" name="期间">
<Hierarchy name="期间" hasAll="true" allMemberName="期间" allMemberCaption="期间" primaryKey="ID" primaryKeyTable="C1_DIM_PERIOD">
<Table name="C1_DIM_PERIOD" alias=""></Table>
<Level name="一级期间" table="C1_DIM_PERIOD" column="YEAR" uniqueMembers="true" ordinalColumn="SEQ_YEAR"/>
<Level name="二级期间" table="C1_DIM_PERIOD" column="QUARTER" uniqueMembers="false" ordinalColumn="SEQ_QUARTER"/>
<Level name="三级期间" table="C1_DIM_PERIOD" column="MONTH" uniqueMembers="false" ordinalColumn="SEQ_MONTH"/>
<Level name="四级期间" table="C1_DIM_PERIOD" column="WEEK" uniqueMembers="false" ordinalColumn="SEQ_WEEK"/>
<Level name="五级期间" table="C1_DIM_PERIOD" column="DAY" uniqueMembers="false" ordinalColumn="SEQ_DAY"/>
</Hierarchy>
</Dimension>
<Dimension type="StandardDimension" foreignKey="ACCOUNT" name="科目">
<Hierarchy name="科目" hasAll="true" allMemberName="科目" allMemberCaption="科目" primaryKey="ID" primaryKeyTable="C1_DIM_ACCOUNT">
<Table name="C1_DIM_ACCOUNT" alias=""></Table>
<Level name="一级科目" table="C1_DIM_ACCOUNT" column="LEVEL_1" uniqueMembers="true"/>
<Level name="二级科目" table="C1_DIM_ACCOUNT" column="LEVEL_2" uniqueMembers="false"/>
<Level name="三级科目" table="C1_DIM_ACCOUNT" column="LEVEL_3" uniqueMembers="false"/>
<Level name="四级科目" table="C1_DIM_ACCOUNT" column="LEVEL_4" uniqueMembers="false"/>
<Level name="五级科目" table="C1_DIM_ACCOUNT" column="LEVEL_5" uniqueMembers="false"/>
<Level name="六级科目" table="C1_DIM_ACCOUNT" column="LEVEL_6" uniqueMembers="false"/>
<Level name="七级科目" table="C1_DIM_ACCOUNT" column="LEVEL_7" uniqueMembers="false"/>
<Level name="八级科目" table="C1_DIM_ACCOUNT" column="LEVEL_8" uniqueMembers="false"/>
<Level name="九级科目" table="C1_DIM_ACCOUNT" column="LEVEL_9" uniqueMembers="false"/>
<Level name="十级科目" table="C1_DIM_ACCOUNT" column="LEVEL_10" uniqueMembers="false"/>
<Level name="十一级科目" table="C1_DIM_ACCOUNT" column="LEVEL_11" uniqueMembers="false"/>
<Level name="十二级科目" table="C1_DIM_ACCOUNT" column="LEVEL_12" uniqueMembers="false"/>
</Hierarchy>
</Dimension>
<Dimension type="StandardDimension" foreignKey="ENTITY" name="组织">
<Hierarchy name="组织" hasAll="true" allMemberName="组织" allMemberCaption="组织" primaryKey="ID" primaryKeyTable="C1_DIM_ENTITY">
<Table name="C1_DIM_ENTITY" alias=""></Table>
<Level name="一级组织" table="C1_DIM_ENTITY" column="LEVEL_1" uniqueMembers="true"/>
<Level name="二级组织" table="C1_DIM_ENTITY" column="LEVEL_2" uniqueMembers="false"/>
<Level name="三级组织" table="C1_DIM_ENTITY" column="LEVEL_3" uniqueMembers="false"/>
<Level name="四级组织" table="C1_DIM_ENTITY" column="LEVEL_4" uniqueMembers="false"/>
<Level name="五级组织" table="C1_DIM_ENTITY" column="LEVEL_5" uniqueMembers="false"/>
<Level name="六级组织" table="C1_DIM_ENTITY" column="LEVEL_6" uniqueMembers="false"/>
<Level name="七级组织" table="C1_DIM_ENTITY" column="LEVEL_7" uniqueMembers="false"/>
<Level name="八级组织" table="C1_DIM_ENTITY" column="LEVEL_8" uniqueMembers="false"/>
<Level name="九级组织" table="C1_DIM_ENTITY" column="LEVEL_9" uniqueMembers="false"/>
<Level name="十级组织" table="C1_DIM_ENTITY" column="LEVEL_10" uniqueMembers="false"/>
<Level name="十一级组织" table="C1_DIM_ENTITY" column="LEVEL_11" uniqueMembers="false"/>
<Level name="十二级组织" table="C1_DIM_ENTITY" column="LEVEL_12" uniqueMembers="false"/>
</Hierarchy>
</Dimension>
<Dimension type="StandardDimension" foreignKey="VERSION" name="版本">
<Hierarchy name="版本" hasAll="true" allMemberName="版本" allMemberCaption="版本" primaryKey="ID" primaryKeyTable="C1_DIM_VERSION">
<Table name="C1_DIM_VERSION" alias=""></Table>
<Level name="版本" table="C1_DIM_VERSION" column="VERSION" uniqueMembers="true"></Level>
</Hierarchy>
</Dimension>
<Measure name="金额" column="V_1" aggregator="sum" visible="true" formatString="0.########"/>
<Measure name="文本" column="V_2" aggregator="max" visible="true" datatype="String"/>
</Cube>
<!-- 第二个CUBE -->
<Cube name="模型二" cache="true" enabled="true">
<Table name="C2_FACT" alias=""></Table>
<Dimension type="TimeDimension" foreignKey="YEAR" name="年">
<Hierarchy name="年" hasAll="true" allMemberName="年" allMemberCaption="年" primaryKey="ID" primaryKeyTable="C2_DIM_YEAR">
<Table name="C2_DIM_YEAR" alias=""></Table>
<Level name="年" table="C2_DIM_YEAR" column="YEAR" uniqueMembers="true" levelType="TimeYears"></Level>
</Hierarchy>
</Dimension>
<Dimension type="StandardDimension" foreignKey="PERIOD" name="期间">
<Hierarchy name="期间" hasAll="true" allMemberName="期间" allMemberCaption="期间" primaryKey="ID" primaryKeyTable="C2_DIM_PERIOD">
<Table name="C2_DIM_PERIOD" alias=""></Table>
<Level name="一级期间" table="C2_DIM_PERIOD" column="YEAR" uniqueMembers="true" ordinalColumn="SEQ_YEAR"/>
<Level name="二级期间" table="C2_DIM_PERIOD" column="QUARTER" uniqueMembers="false" ordinalColumn="SEQ_QUARTER"/>
<Level name="三级期间" table="C2_DIM_PERIOD" column="MONTH" uniqueMembers="false" ordinalColumn="SEQ_MONTH"/>
<Level name="四级期间" table="C2_DIM_PERIOD" column="WEEK" uniqueMembers="false" ordinalColumn="SEQ_WEEK"/>
<Level name="五级期间" table="C2_DIM_PERIOD" column="DAY" uniqueMembers="false" ordinalColumn="SEQ_DAY"/>
</Hierarchy>
</Dimension>
<Dimension type="StandardDimension" foreignKey="ACCOUNT" name="科目">
<Hierarchy name="科目" hasAll="true" allMemberName="科目" allMemberCaption="科目" primaryKey="ID" primaryKeyTable="C2_DIM_ACCOUNT">
<Table name="C2_DIM_ACCOUNT" alias=""></Table>
<Level name="一级科目" table="C2_DIM_ACCOUNT" column="LEVEL_1" uniqueMembers="true"/>
<Level name="二级科目" table="C2_DIM_ACCOUNT" column="LEVEL_2" uniqueMembers="false"/>
<Level name="三级科目" table="C2_DIM_ACCOUNT" column="LEVEL_3" uniqueMembers="false"/>
<Level name="四级科目" table="C2_DIM_ACCOUNT" column="LEVEL_4" uniqueMembers="false"/>
<Level name="五级科目" table="C2_DIM_ACCOUNT" column="LEVEL_5" uniqueMembers="false"/>
<Level name="六级科目" table="C2_DIM_ACCOUNT" column="LEVEL_6" uniqueMembers="false"/>
<Level name="七级科目" table="C2_DIM_ACCOUNT" column="LEVEL_7" uniqueMembers="false"/>
<Level name="八级科目" table="C2_DIM_ACCOUNT" column="LEVEL_8" uniqueMembers="false"/>
<Level name="九级科目" table="C2_DIM_ACCOUNT" column="LEVEL_9" uniqueMembers="false"/>
<Level name="十级科目" table="C2_DIM_ACCOUNT" column="LEVEL_10" uniqueMembers="false"/>
<Level name="十一级科目" table="C2_DIM_ACCOUNT" column="LEVEL_11" uniqueMembers="false"/>
<Level name="十二级科目" table="C2_DIM_ACCOUNT" column="LEVEL_12" uniqueMembers="false"/>
</Hierarchy>
</Dimension>
<Dimension type="StandardDimension" foreignKey="ENTITY" name="组织">
<Hierarchy name="组织" hasAll="true" allMemberName="组织" allMemberCaption="组织" primaryKey="ID" primaryKeyTable="C2_DIM_ENTITY">
<Table name="C2_DIM_ENTITY" alias=""></Table>
<Level name="一级组织" table="C2_DIM_ENTITY" column="LEVEL_1" uniqueMembers="true"/>
<Level name="二级组织" table="C2_DIM_ENTITY" column="LEVEL_2" uniqueMembers="false"/>
<Level name="三级组织" table="C2_DIM_ENTITY" column="LEVEL_3" uniqueMembers="false"/>
<Level name="四级组织" table="C2_DIM_ENTITY" column="LEVEL_4" uniqueMembers="false"/>
<Level name="五级组织" table="C2_DIM_ENTITY" column="LEVEL_5" uniqueMembers="false"/>
<Level name="六级组织" table="C2_DIM_ENTITY" column="LEVEL_6" uniqueMembers="false"/>
<Level name="七级组织" table="C2_DIM_ENTITY" column="LEVEL_7" uniqueMembers="false"/>
<Level name="八级组织" table="C2_DIM_ENTITY" column="LEVEL_8" uniqueMembers="false"/>
<Level name="九级组织" table="C2_DIM_ENTITY" column="LEVEL_9" uniqueMembers="false"/>
<Level name="十级组织" table="C2_DIM_ENTITY" column="LEVEL_10" uniqueMembers="false"/>
<Level name="十一级组织" table="C2_DIM_ENTITY" column="LEVEL_11" uniqueMembers="false"/>
<Level name="十二级组织" table="C2_DIM_ENTITY" column="LEVEL_12" uniqueMembers="false"/>
</Hierarchy>
</Dimension>
<Dimension type="StandardDimension" foreignKey="VERSION" name="版本">
<Hierarchy name="版本" hasAll="true" allMemberName="版本" allMemberCaption="版本" primaryKey="ID" primaryKeyTable="C2_DIM_VERSION">
<Table name="C2_DIM_VERSION" alias=""></Table>
<Level name="版本" table="C2_DIM_VERSION" column="VERSION" uniqueMembers="true"></Level>
</Hierarchy>
</Dimension>
<Measure name="金额" column="V_1" aggregator="sum" datatype="Numeric" formatString="0.########"></Measure>
<Measure name="文本" column="V_2" aggregator="max" visible="true" datatype="String"/>
</Cube>
<!--第三个立方体-->
<Cube name="模型三" cache="true" enabled="true">
<Table name="C3_FACT" alias=""></Table>
<Dimension type="TimeDimension" foreignKey="YEAR" name="年">
<Hierarchy name="年" hasAll="true" allMemberName="年" allMemberCaption="年" primaryKey="ID" primaryKeyTable="C3_DIM_YEAR">
<Table name="C3_DIM_YEAR" alias=""></Table>
<Level name="年" table="C3_DIM_YEAR" column="YEAR" uniqueMembers="true" levelType="TimeYears"></Level>
</Hierarchy>
</Dimension>
<Dimension type="StandardDimension" foreignKey="PERIOD" name="期间">
<Hierarchy name="期间" hasAll="true" allMemberName="期间" allMemberCaption="期间" primaryKey="ID" primaryKeyTable="C3_DIM_PERIOD">
<Table name="C3_DIM_PERIOD" alias=""></Table>
<Level name="一级期间" table="C3_DIM_PERIOD" column="YEAR" uniqueMembers="true" ordinalColumn="SEQ_YEAR"/>
<Level name="二级期间" table="C3_DIM_PERIOD" column="QUARTER" uniqueMembers="false" ordinalColumn="SEQ_QUARTER"/>
<Level name="三级期间" table="C3_DIM_PERIOD" column="MONTH" uniqueMembers="false" ordinalColumn="SEQ_MONTH"/>
<Level name="四级期间" table="C3_DIM_PERIOD" column="WEEK" uniqueMembers="false" ordinalColumn="SEQ_WEEK"/>
<Level name="五级期间" table="C3_DIM_PERIOD" column="DAY" uniqueMembers="false" ordinalColumn="SEQ_DAY"/>
</Hierarchy>
</Dimension>
<Dimension type="StandardDimension" foreignKey="ACCOUNT" name="科目">
<Hierarchy name="科目" hasAll="true" allMemberName="科目" allMemberCaption="科目" primaryKey="ID" primaryKeyTable="C3_DIM_ACCOUNT">
<Table name="C3_DIM_ACCOUNT" alias=""></Table>
<Level name="一级科目" table="C3_DIM_ACCOUNT" column="LEVEL_1" uniqueMembers="true"/>
<Level name="二级科目" table="C3_DIM_ACCOUNT" column="LEVEL_2" uniqueMembers="false"/>
<Level name="三级科目" table="C3_DIM_ACCOUNT" column="LEVEL_3" uniqueMembers="false"/>
<Level name="四级科目" table="C3_DIM_ACCOUNT" column="LEVEL_4" uniqueMembers="false"/>
<Level name="五级科目" table="C3_DIM_ACCOUNT" column="LEVEL_5" uniqueMembers="false"/>
<Level name="六级科目" table="C3_DIM_ACCOUNT" column="LEVEL_6" uniqueMembers="false"/>
<Level name="七级科目" table="C3_DIM_ACCOUNT" column="LEVEL_7" uniqueMembers="false"/>
<Level name="八级科目" table="C3_DIM_ACCOUNT" column="LEVEL_8" uniqueMembers="false"/>
<Level name="九级科目" table="C3_DIM_ACCOUNT" column="LEVEL_9" uniqueMembers="false"/>
<Level name="十级科目" table="C3_DIM_ACCOUNT" column="LEVEL_10" uniqueMembers="false"/>
<Level name="十一级科目" table="C3_DIM_ACCOUNT" column="LEVEL_11" uniqueMembers="false"/>
<Level name="十二级科目" table="C3_DIM_ACCOUNT" column="LEVEL_12" uniqueMembers="false"/>
</Hierarchy>
</Dimension>
<Dimension type="StandardDimension" foreignKey="ENTITY" name="组织">
<Hierarchy name="组织" hasAll="true" allMemberName="组织" allMemberCaption="组织" primaryKey="ID" primaryKeyTable="C3_DIM_ENTITY">
<Table name="C3_DIM_ENTITY" alias=""></Table>
<Level name="一级组织" table="C3_DIM_ENTITY" column="LEVEL_1" uniqueMembers="true"/>
<Level name="二级组织" table="C3_DIM_ENTITY" column="LEVEL_2" uniqueMembers="false"/>
<Level name="三级组织" table="C3_DIM_ENTITY" column="LEVEL_3" uniqueMembers="false"/>
<Level name="四级组织" table="C3_DIM_ENTITY" column="LEVEL_4" uniqueMembers="false"/>
<Level name="五级组织" table="C3_DIM_ENTITY" column="LEVEL_5" uniqueMembers="false"/>
<Level name="六级组织" table="C3_DIM_ENTITY" column="LEVEL_6" uniqueMembers="false"/>
<Level name="七级组织" table="C3_DIM_ENTITY" column="LEVEL_7" uniqueMembers="false"/>
<Level name="八级组织" table="C3_DIM_ENTITY" column="LEVEL_8" uniqueMembers="false"/>
<Level name="九级组织" table="C3_DIM_ENTITY" column="LEVEL_9" uniqueMembers="false"/>
<Level name="十级组织" table="C3_DIM_ENTITY" column="LEVEL_10" uniqueMembers="false"/>
<Level name="十一级组织" table="C3_DIM_ENTITY" column="LEVEL_11" uniqueMembers="false"/>
<Level name="十二级组织" table="C3_DIM_ENTITY" column="LEVEL_12" uniqueMembers="false"/>
</Hierarchy>
</Dimension>
<Dimension type="StandardDimension" foreignKey="VERSION" name="版本">
<Hierarchy name="版本" hasAll="true" allMemberName="版本" allMemberCaption="版本" primaryKey="ID" primaryKeyTable="C3_DIM_VERSION">
<Table name="C3_DIM_VERSION" alias=""></Table>
<Level name="版本" table="C3_DIM_VERSION" column="VERSION" uniqueMembers="true"></Level>
</Hierarchy>
</Dimension>
<Measure name="金额" column="V_1" aggregator="sum" visible="true" formatString="0.########"/>
<Measure name="文本" column="V_2" aggregator="max" visible="true" datatype="String"/>
</Cube>
</Schema>
(完整的schemal)
ps:
Hierarchy hasAll:包含所有的成员;
allMemberName:所有成员的名字;
allMemberCaption:表示在层上显示的内容
ordinalColumn:level上成员的顺序,按这个属性指定
需要注意的是:分析系统对这些维度有2个方面的管理:
一个是逻辑上的层次结构;一个是分析维度,
以期间为例,如下图所示:
分析相关数据库表设计:
逻辑部分统一放到COMM_OBJ表当中
表中关键字段为id,name,parnet等。
建立五张表如下,存放5个维度的数据。
五张维度表,数据采取扁平化方式存放。如下图:
逻辑结构和分析结构通过id加以关联。
MDX
mdx语法:“{}”代表集合。
由于我们是根据用户配置生成MDX,我们重点研究一下如何 动态生成 MDX语句。我们是通过生成select、from、where三个字句动态生成mdx字符串,
我们知道,formModel中记录了用户自定义的分析表单信息,或者说用户对分析模型的要求,以我们定义一个列维为例 ,用户定义的 列维度的结构是:组—》选择的维度类型—》维度成员。
结构是:List<List<List<DimMember>>>,最外层的集合代表组,中间一层list表示维度(如项目、组织机构、年度等),最里层的集合是具体维度成员的集合。
假设要形成上图的列组合,这个列分三组,(组用不同颜色标注),这个列涉及年度与版本。
Mdx的关于列的部分语句应该为;
{
{[年].[2014年] }*{[版本].[计划] ,[版本].[实际]},//黄色组
{[年].[2016年] }*{[版本].[实际]},//灰色组
{[年].[2017年] }*{[版本].[计划]}//蓝色组
}
动态形成它的代码为:
Listmembers=List<DimMember>;//选择的成员
Listdims=List< members > ;//选择的维度,如项目、机构等
Listgroups= List< dims >; //定义的祖
StringBufferstrBuffer=new StringBuffer(); //y用于拼接mdx语句
strBuffer.append("{");//最外层大括号,它里面的括号表示组
For(int k = 0; k < groups.size(); k++){ //遍历祖
List dims= groups.get(k); //获取一个组中选定的维度
for (int i = 0; i < dims.size(); i++) {
strBuffer.append("{");//类似{[年].[2014年] }
List<DimMember> members= dims.get(i);
//遍历维度成员
for (int j = 0; j <members.size(); j++) {
DimMember member=members.get(j);
Dimension dim=member.getDimension();
……//形成类似[年].[2014年]的结构
}
strBuffer.append("}");
if (i != membersList.size() - 1) {
strBuffer.append("*");
}
}
}
}
按以上办法,形成列、行、页面等四个方面的字句。不过,页面等只有2层集合(因为他们没有组的概念)
轴:
用 on {axis}语法来把维度分配到轴(Axis,复数 Axes)上,一个查询可以有多个轴。如 A on columns, B on rows跟 B on rows, A on columns 是一样的。
轴用 axis(0),axis(1),axis(2)...表示,前五个轴可以使用别名 Columns,Rows,Pages, Chapters,Sections。因此 on Columns 等价于 on axis(0)。超过 5 个轴时只能用 axis(5),axis(6)...来表示(极少会需要这么多的轴)。
很多实现(包括 Mondrian)支持用数字表示轴,因此 on Columns 可以写成 on 0。
根据MDX查询结果集与后端表单模型形成前端网格模型的方法:
主要构建前端页面需要的五个方面信息:
l 构建视点信息
l 构建页面信息
l 构建行信息
l 构建列信息
l 构建列信息
l 构建事实单元格信息
先看几个 API说明:
MDX查询返回Result,reuslt中,axis是比较重要的组件。
先看Axis、Position、MemberAPI说明:
public interface Axis
AAxis is a component of a Result. It contains a list of Positions.
Axis是Result一个组件,它是包含Positions的的一个List集合
A Position is an item on an Axis. It containsone or more Members.
Position本身是Axis一个项目(item),它包含一个或者多个成员(member).
public interface Member
extendsOlapElement, Comparable, Annotated
AMember is a 'point' on a dimension of a cube. Examples are[Time].[1997].[January], [Customer].[All Customers], [Customer].[USA].[CA],[Measures].[Unit Sales].
Everymember belongs to a Level of a Hierarchy. Members except the root member have aparent, and members not at the leaf level have one or more children.
Measuresare a special kind of member. They belong to their own dimension, [Measures].
Thereare also special members representing the 'All' value of a hierarchy, the nullvalue, and the error value.
Memberscan have member properties. Their Level.getProperties() defines which areallowed.
A Cell is an item in the grid of a Result. It is returned by Result.getCell(int[]).
Returnsthe cell at a given set of coordinates. For example, in a result with 4 columnsand 6 rows, the top-left cell has coordinates [0, 0], and the bottom-right cellhas coordinates [3, 5].
返回给定坐标系的单元格。 例如,在具有4列和6行的结果中,左上方的单元格具有坐标[0,0],右下方单元格具有坐标[3,5]。
l 构建视点信息:
根据formModel中的信息,取得视点维度的id与维度成员的id信息,把视点中每个维度的第一个成员id,放入int[],同时,把视点维度信息拼接成字符串,
l 构建页面信息:
根据formModel中的信息,取得页面维度的id与维度成员的id信息,把页面中每个维度的第一个成员id,放入int[]
l 构建行信息:
根据formModel中的信息,取得行维度的id与维度成员的id信息,把页面中每个维度的第一个成员id,放入int[][],和页面、视点不同的是,描述页面行维度信息的是个二维数组,因为行维可以由多个维度组成。同时,叶需要取得行维度id的字符串信息。
int[][] rowDimInfo = null; //存放行维度成员id的二维数组
Result result=null;
Axis rowAxis = result.getAxes()[1];
//获取行的数量(行维上)
int rowNum =rowAxis.getPositions().size();
//获取列的数量(行维上的)
int colNum = rowAxis.getPositions().get(0).size();
rowDimInfo = new int[rowNum][colNum];
for (int i = 0; i < rowNum; i++) {
for (int j = 0; j < colNum; j++) {
Member member =rowAxis.getPositions().get(i).get(j);
…..把mondrian的member,转换为我们自定义的维度成员
rowDimInfo[i][j] =dimMember.getMemberId();
}
}
……获取行维度id拼接的字符串
l 构建列信息:
构建列信息和构建行信息类似。不过,在构建列信息数组的时候,可以把行列数组下标的顺序调整一下,这样,可以方便后面的事实数据定位。
构建行信息及构建列信息,特别是构建列信息的时候,有三个概念要注意:
1)如果mdx中,类似 [组织].Members的选择,成员数量会多一个(Al)l,不过,我们系统的设计,事先都选定了成员,不存在这个问题;
2)度量作为特殊维度会出现在列维度当中,因此计算列维度行数的语句为:(Measures area special kind of member)
colAxis.getPositions().get(0).size() -1;
3)另外一个是,度量是特殊的维度,会加载列维度当中,如果我们的模型有2个度量,那就的注意int[][]数组的大小:
new int[rowNum][colNum / 2]
l 构建事实单元格信息
introwCount=result.getAxes()[1].getPositions().size();
intcolCount = result.getAxes()[0].getPositions().size();
FactCell[][]factCells = new FactCell [rowCount][colCount];
如果有2个度量:则factCells为:
FactCell[][]factCells = new FactCell [rowCount][colCount/2];
根据rowCount、colCount遍历Result,形成factCells
构建基于事实表单元格数据的时候,要注意计算列出现"Infinity"的情形。
构建事实单元格的时候,我们另外定义了FactCell对象,这个对象中,含有每个事实数据的“坐标信息”,坐标信息包括行维度成员、列维度成员、视点成员、页面成员等。
维度管理:mondrian
设计相关概念:
有2个关键的类,
一个是与界面的分析表格视图(view)对应的类:viewGrid
一个是后端分析模型的类:formModel
buildViewGrid(formModelf, Result result,PageLayout pageLayout);
buildViewGrid的参数为 formModel,Result及前端选择的页面pageLayout
buildViewGrid方法用于从formModel构建viewGrid;
buildViewGrid
首先是从formModel基础信息中,构建MDX语句,
根据mdx语句查询结果集,
根据结果集+formModel+页面布局当中的信息,构建viewGrid模型;
web端就是根据viewGrid在绘制呈现给用户的界面。
下一章节具体描述buildViewGrid方法的实现吧。
private int[] buildViewInfo(FormShadow form, StringBuffer viewDimsBuffer){
try{
//得到视点维度成员的集合,这是一个2维数组
List<List<DimMember>> viewMbrs =form.getViewMembers();
int count = viewMbrs.size();
int[] gridView =new int[count];
//遍历视点
for (int i = 0; i < count; i++) {
//取得视点中的维度成员对象
DimMember member = viewMbrs.get(i).get(0);
//取得维度成员对象的id属性,且把它放进数组
l gridView[i] = member.getMemberId();
//对应维度id存放在StringBuffer
if(i!=count-1){
viewDimsBuffer.append(member.getDimension().getId()+",");
}else{
viewDimsBuffer.append(member.getDimension().getId()+"");
}
}
return gridView;
}catch (Exception e) {
loggerUtil.log("buildViewInfo", e);
}
return null;
}