Mondrian是一个OLAP分析的引擎,主要工作是根据事先配置好的schema,将输入的多维分析语句MDX(Multidimensional Expressions )翻译成目标数据库/数据引擎的执行语言(比如SQL)。
Schema
一个模式文件定义了一个多维数据库。模式中包含了一个逻辑模型,逻辑模型
由数据立方Cube,层次Hierarchies,成员members,以及一个将逻辑模型与物理模型(数据源)映射组成。
Cube
一个逻辑模型内可以有多个Cube,一个Cube则是一系列维度Dimension
和度量Measure
组成,当前Cube内所有度量和未声明所用表的维度都公用一个事实表。可以在Cube内使用Table标签声明该公用事实表。
<Schema>
<Cube>
<Table />
<Dimension></Dimension>
......
<Measure />
......
</Cube>
</Schema>
属性名 | 含义 |
---|---|
name | Cube 的名字 |
caption | 标题 , 在表示层显示的 |
cache | 是否对 Cube 对应的实表用 mondrian 进行存储 , 默认为 true |
enabled | 是布尔型的 , 如果是被激活 ,Cubes 就执行 , 否则就不予理睬,默认为 true |
Dimension
维度是一系列层次Hierarchies
的集合,维度一般情况下使用的当前Cube所公用的事实表,不过维度可以声明其相对应的维度表。
属性名 | 含义 |
---|---|
name | Dimension 的名称 |
type | 类型,有两个可选的类型: StandarDimension 和 TimeDimension ,默认为 StandardDimension |
caption | 标题 , 在表示层显示的 |
UsagePrefix | 加前缀 , 消除歧义 |
foreignKey | 外键,对应事实表中的一个列,它通过 元素中的主键属性连接起来 |
Hierarchies
由一系列Levels组成,可以使用Table配合维度声明当前维度表,若没有特别指定,则默认该Hierarchies使用的是Cube的公用事实表。
<Dimension visible="true" name="kkkk" foreignKey="XXX001">
<Hierarchy primaryKey="XXX001" hasAll="true" name="aaaaa">
<Table name="XXX" />
<Level name="kkkk" visible="true" column="bbb002num" nameColumn='bbb002name' orderByColumn='bbb002num' type="String"/>
</Hierarchy>
</Dimension>
常用属性如下
属性名 | 含义 |
---|---|
name | Hierarchy 的名称,该值可以为空,为空时表示 Hirearchy 的名字和 Dimension 的名字相同。当一个 Dimension 有多个 Hierarchy 时,注意 name 值要唯一。 |
hasAll | 布尔型的 , 决定是否包含全部的成员 member |
allMemberName | 所有成员的名字 , 也就是总的标题 , 例如: allMemberName= “全部产品” |
allLevelName | 所有级别的名字,它会覆盖其下所有的 Member 的 name 和所有的 Level 的 name 属性的值。 |
allMemberCaption | 例如 : allMemberCaption= “全部产品”这个是在表示层显示的内容 |
PrimaryKey | 通过主键来确定成员,该主键指的是成员表中的主键,该主键同时要与 Dimension 里设置的 foreignKey 属性对应的字段形成外键对应关系 |
primaryKeyTable | 如果成员表不只一个,而是多个表通过 join 关系形成的,那么就要通过这个属性来指明 join 的这些表中,哪一个与 Dimension 里设置的 foreignKey 属性形成外键关系。通过该属性来指明主表 |
caption | 标题 , 在表示层显示的 |
Level
任何一个Hierarchy都由一个或多个Level组成,在同一Hierarchy下的多个Levels可以组成一个结构树,Level的先后顺序决定了它们的位置关系。常用属性如下
属性名 | 含义 |
---|---|
name | 名称 |
table | 该 Level 要使用的表名 |
column | 用上面指定的表中某一列作为该 Level 的关键字 |
nameColumn | 用来显示的时候使用,如果不定义,那么就采用上面的 column 的值来进行显示。 |
orderByColumn | 定义该 Level 上的成员的显示顺序,如果不指定,那么采用 column 的值。 |
type | 数据类型,默认值为 string 。当然还可以是 Numeric 、 Integer 、 Boolean 、 Date 等。 |
Measure
度量是用来处理数据的核心规则,每个度量都有一个事实表中的对应列和一个aggregator
,aggregator
通常包括:sum,count,min,max,avg,distinct-count
。其中distinct-count
在使用包含父-子层级的数据立方时存在一些限制条件。
<CalculatedMember name="行业分类基地数占比" dimension="Measures" formatString="0.00%" formula="([Measures].[见习基地数] / ([Measures].[见习基地数], [行业分类].CurrentMember.Parent))"/>
<CalculatedMember name="行业分类人数占比" dimension="Measures" formatString="0.00%" formula="[Measures].[备案人数]/[行业分类].[aaa022].[All aaa022s]"/>
属性名 | 含义 |
---|---|
name | 名称 |
aggregator | 要采用的计算函数 |
column | 要计算的列名 |
formatString | 计算结果的显示格式。 |
visible | 是否可见 |
datatype | 数据类型,默认为 Numeric |
formatter | 采用类来对该 Measure 的值进行格式,具体参考 Level 的 formatter 属性。 |
caption | 标题,用来显示时使用。 |
假设存在三张表student
,score
,subject1
,class
。需求如下:
① 查询各科考试人数和成绩最大值最小值平均值
② 下钻可以查看具体学生成绩,学生详细信息等。
各表简单表结构如下:
表名 | 字段名 | 属性名 | 主外键 |
---|---|---|---|
student | stu_id | 学号 | 主键 |
student | cla_id | 班级编号 | 外键 |
student | stu_name | 姓名 | |
student | stu_sex | 性别 | |
score | sco_id | 成绩编号 | 主键 |
score | stu_id | 学号 | 外键 |
score | sub_id | 学科编号 | 外键 |
score | sco_num | 分数 | |
subject1 | sub_id | 学科编号 | 主键 |
subject1 | sub_name | 学科名 | |
class | cla_id | 班级编号 | 主键 |
class | cla_name | 班级名称 |
Step 1. 根据需求,确定主表score
<?xml version="1.0" encoding="utf-8"?>
<Schema name="成绩分析">
<Cube name="成绩分析" visible="true" cache="true" enabled="true">
<Table name=""/>
...
</Cube>
</Schema>
Step 2. 分析查询维度及其所在表,主要维度为表subject1
内字段学习科目sub_name
。操作时需要使用外键关联主表score
及表subject1
,示例如下:
<Dimension visible="true" name="学科相关" foreignKey="sub_id">
<Hierarchy primaryKey="sub_id" visible="true" hasAll="true">
<Table name="subject1" />
<Level name="学科名称" visible="true" column="sub_name" type="String"/>
</Hierarchy>
</Dimension>
需要注意的是表class
内的班级维度cla_name
,需要使用Join
来关联三个表。
Step 3. 设计实现度量如下
<Measure name="学生人数" column="stu_id" aggregator="distinct-count" visible="true"/>
<Measure name="成绩(最大)" column="sco_num" aggregator="max" visible="true"/>
<Measure name="成绩(最小)" column="sco_num" aggregator="max" visible="true"/>
<Measure name="成绩(平均)" column="sco_num" aggregator="avg" visible="true"/>
Step 4. 分析下钻维度及其实现。需要查看的下钻信息主要有表student
内字段stu_name
和stu_sex
及表score
内字段sco_num
。实现如下:
<Dimension visible="false" name="分数" >
<Hierarchy visible="true" hasAll="true">
<Level name="分数" visible="true" column="sco_num" type="Integer"/>
</Hierarchy>
</Dimension>
<Dimension visible="false" name="学生相关" foreignKey="stu_id">
<Hierarchy primaryKey="stu_id" visible="true" hasAll="true">
<Table name="student" />
<Level name="性别" visible="true" column="stu_sex" type="String"/>
<Level name="姓名" visible="true" column="stu_name" type="String"/>
</Hierarchy>
</Dimension>
以2.2 简单数据模型配置步骤示例
中表结构及数据为基础
①性别比例
<CalculatedMember name="单个学生考试的参与率" dimension="Measures" formatString="0.00%" formula="[Measures].[学生人数] / [性别].[stu_sex].[ALL stu_sexs])"/>
②班级比例
<CalculatedMember name="单个学生考试的参与率" dimension="Measures" formatString="0.00%" formula="[Measures].[学生人数] / [班级].[cla_id].[ALL cla_ids])"/>
③单个学生考试的参与率(已考科目/所有科目)
<CalculatedMember name="单个学生考试的参与率" dimension="Measures" formatString="0.00%" formula="([Measures].[已考科目数] / ([Measures].[已考科目数], [学科名称].CurrentMember.Parent))"/>
Mondrian官方使用文档翻译-(1) - 走在IT路上
Mondrian官方使用文档翻译-(2) - 走在IT路上
Pentaho Mondrian Documentation
Mondrian Schema详解 - 难得糊涂
多维数据化分析之MDX schema入门