OLAP分析(四)--mondrian schemal

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/wh_xia_jun/article/details/90200178

本文重点总结mondrian4 schemal的写法及其趟过的各种坑,我的mondrian版本是4.7.0.0-12

不涉及雪花模型、共享维、Virtual cubes,attribute的property、Closure tables、聚合、调优 等,总结最基础的schemal,毕竟财政业务相对是比较简单的。

olap发展一直不太好,我觉得很重要的原因就是schemal等的原因,再加上展示麻烦。mdx很容易,弄过sql的人,搞mdx倒是蛮快的。

和数据库连接弄好了,我们当然是为了查询需要的数据。我们先利用OLAP4J的query对象的,进行相关查询。

查询前我理解最好校验一下,olap4j文档上说,校验做了3件事情:

1)Performs default selections 执行默认选择

2)Validates the presence of at least one dimensions on both ROWS and COLUMNS

       axis  校验在行、列轴上是否存在至少一个维度

3)Tries to build a MDX parse tree 尝试构建MDX分析树

我们开始Creating selections to include or exclude from a query:

做这件事情,其实是2步:

1、找基准点

2、基于基准点进行操作

        // olap4j的mdx接口,是一个jdbc实现,推荐
        System.out.println("\r\n===================olap4j接口==================");
        String mdxStr = "select {[年].Members} on columns,{[组织].Members} on rows from 模型一";
        // 建立连接
        String strUrl = "jdbc:mondrian:";
        strUrl += "Jdbc=" + url;
        strUrl += ";JdbcUser=" + userName;
        strUrl += ";JdbcPassword=" + password;
        // strUrl += ";Catalog=" + xmlFile;
        strUrl += ";CatalogContent=" + getCatalogContent();
        Class.forName("mondrian.olap4j.MondrianOlap4jDriver");
        Connection olap4jConn = DriverManager.getConnection(strUrl);
        OlapConnection olapConn = (OlapConnection) olap4jConn.unwrap(OlapConnection.class);
        NamedList<Cube> cubes =
                olapConn.getOlapSchema().getCubes();
        Cube cube = cubes.get("模型一");
        Query myQuery =
                new Query("model1Query", cube);
        myQuery.execute();
       System.out.println("------------myQuery------------:"+myQuery);
        QueryDimension year = myQuery.getDimension("Year");
        QueryDimension entity = myQuery.getDimension("Entity");
        myQuery.getAxis(Axis.COLUMNS).addDimension(year);
        myQuery.getAxis(Axis.ROWS).addDimension(entity);
        Member year2017 =
                cube.lookupMember(
                        IdentifierNode.ofNames ("Year", "2017年")
                                .getSegmentList());
        year.include(year2017);
        myQuery.validate();
        System.out.println(
                myQuery.getSelect().toString());

        String s=myQuery.getSelect().toString();
        System.out.println("s:"+s);

        CellSet cellSet =   myQuery.execute();
        // 输出结果
        CellSetFormatter formatter = new RectangularCellSetFormatter(false);
        formatter.format(cellSet, new PrintWriter(System.out, true));

执行结果:

SELECT
{[Year].[2017年]} ON COLUMNS,
{[Entity].[All Entitys]} ON ROWS
FROM [模型一]
s:SELECT
{[Year].[2017年]} ON COLUMNS,
{[Entity].[All Entitys]} ON ROWS
FROM [模型一]
10:13:36.394 [mondrian.rolap.RolapResultShepherd$executor_2] DEBUG mondrian.spi.impl.JdbcDialectImpl - JdbcDialectImpl.getType Dialect- ORACLE, Column-COUNT(DISTINCT"YEAR") is of internal type INT. JDBC type was 2.  Column precision=0.  Column scale=0
10:13:36.462 [mondrian.rolap.agg.SegmentCacheManager$sqlExecutor_2] DEBUG mondrian.spi.impl.JdbcDialectImpl - JdbcDialectImpl.getType Dialect- ORACLE, Column-c0 is of internal type OBJECT. JDBC type was -9.  Column precision=20.  Column scale=0
10:13:36.462 [mondrian.rolap.agg.SegmentCacheManager$sqlExecutor_2] DEBUG mondrian.spi.impl.JdbcDialectImpl - JdbcDialectImpl.getType Dialect- ORACLE, Column-c0 is of internal type OBJECT. JDBC type was -9.  Column precision=20.  Column scale=0
10:13:36.462 [mondrian.rolap.agg.SegmentCacheManager$sqlExecutor_2] DEBUG mondrian.spi.impl.JdbcDialectImpl - JdbcDialectImpl.getType Dialect- ORACLE, Column-m0 is of internal type OBJECT. JDBC type was 2.  Column precision=0.  Column scale=0
10:13:36.462 [mondrian.rolap.agg.SegmentCacheManager$sqlExecutor_2] DEBUG mondrian.spi.impl.JdbcDialectImpl - JdbcDialectImpl.getType Dialect- ORACLE, Column-c0 is of internal type OBJECT. JDBC type was -9.  Column precision=20.  Column scale=0
10:13:36.462 [mondrian.rolap.agg.SegmentCacheManager$sqlExecutor_2] DEBUG mondrian.spi.impl.JdbcDialectImpl - JdbcDialectImpl.getType Dialect- ORACLE, Column-c0 is of internal type OBJECT. JDBC type was -9.  Column precision=20.  Column scale=0
10:13:36.462 [mondrian.rolap.agg.SegmentCacheManager$sqlExecutor_2] DEBUG mondrian.spi.impl.JdbcDialectImpl - JdbcDialectImpl.getType Dialect- ORACLE, Column-m0 is of internal type OBJECT. JDBC type was 2.  Column precision=0.  Column scale=0
10:13:36.462 [mondrian.rolap.agg.SegmentCacheManager$sqlExecutor_2] DEBUG mondrian.spi.impl.JdbcDialectImpl - JdbcDialectImpl.getType Dialect- ORACLE, Column-c0 is of internal type OBJECT. JDBC type was -9.  Column precision=20.  Column scale=0
10:13:36.462 [mondrian.rolap.agg.SegmentCacheManager$sqlExecutor_2] DEBUG mondrian.spi.impl.JdbcDialectImpl - JdbcDialectImpl.getType Dialect- ORACLE, Column-c0 is of internal type OBJECT. JDBC type was -9.  Column precision=20.  Column scale=0
10:13:36.462 [mondrian.rolap.agg.SegmentCacheManager$sqlExecutor_2] DEBUG mondrian.spi.impl.JdbcDialectImpl - JdbcDialectImpl.getType Dialect- ORACLE, Column-m0 is of internal type OBJECT. JDBC type was 2.  Column precision=0.  Column scale=0
|             | 2017年       |
+-------------+-------------+
| All Entitys | 79440368.57 |

为进一步测试,我写4个测试程序:

测试程序测试foodmart例子。(用mondrian与olap4j分别实现)

一个测试程序测试非税(用mondrian与olap4j分别实现);

用mondrian4的规范重写一遍非税与foodmart的schemal。

再原来的3.0版本基础上,重写了,报错:

RolapSchema$MondrianSchemaException: Dimension 'Year' not found in this cube, but there is a schema dimension of that name. Did you intend to create cube dimension referring to that schema dimension? (in ForeignKeyLink) (at line 42, column 10)

原来可能是是3.0引用方式,4.0中schemal不认识它们?

动手按4.0文档的内容重新写schemal如下:

<?xml version="1.0" encoding="UTF-8"?>
<Schema name="OlapSchema" metamodelVersion="4.0">

  <PhysicalSchema>
    <Table name="C1_FACT"/>
    <Table name="C1_DIM_YEAR"/>
    <Table name="C1_DIM_ACCOUNT"/>
    <Table name="C1_DIM_ENTITY"/>
    <Table name="C1_DIM_PERIOD"/>
  </PhysicalSchema>

  <Cube name="模型一" defaultMeasure="金额">


    <Dimensions>
      <Dimension name="Year"  table="C1_DIM_YEAR" key="Id" >
        <Attributes>
          <Attribute  name="Id"  keyColumn="ID"  hasHierarchy='false'/>
           <Attribute  name="YearName"   hasHierarchy='false'>
             <Key>
               <Column name="YEAR"/>
             </Key>
          </Attribute>
          <!--和上面是等价的写法-->
          <!--<Attribute  name="YearName"   keyColumn="YEAR" hasHierarchy='false'/>-->

        </Attributes>
        <Hierarchies>
          <Hierarchy name="YearLy" hasAll="true">
            <Level attribute="YearName"/>
          </Hierarchy>
        </Hierarchies>
      </Dimension>

      <Dimension name="Period" table="C1_DIM_PERIOD"  key="Id">
        <Attributes>
          <Attribute  name="Id"  keyColumn="ID" columnName="ID" />
          <Attribute  name="Year"  keyColumn="ID" columnName="YEAR" />
          <Attribute  name="Quarter"  keyColumn="ID" columnName="QUARTER"  />
          <Attribute  name="Month"  keyColumn="ID" columnName="MONTH"/>
        </Attributes>
        <Hierarchy name="Period" hasAll="false" defaultMember="[Period].[全年合计].[4季].[12]" >
          <Level attribute="Year"/>
          <Level attribute="Quarter"/>
          <Level attribute="Month"/>
        </Hierarchy>
      </Dimension>

      <Dimension name="Entity" table="C1_DIM_ENTITY" key="Id">
        <Attributes>
          <Attribute  name="Id"  keyColumn="ID"  hasHierarchy='false'/>
          <!--以下写法逻辑上是否是错误的?-->
          <!--方法1-->
<!--          <Attribute  name="Province" keyColumn="LEVEL_1" hasHierarchy='true'>
          </Attribute>-->
          <!--方法2-->
           <!-- <Attribute  name="Province"  keyColumn="ID" columnName="LEVEL_1" hasHierarchy='true'/>-->
          <!--方法3-->
          <Attribute  name="Province"  column="LEVEL_1" hasHierarchy='true'>
            <Key>
              <Column table="C1_DIM_ENTITY" name="ID"/>
              </Key>
          </Attribute>


          <Attribute  name="City" keyColumn="ID" columnName="LEVEL_2"  hasHierarchy='true'>
          </Attribute>
          <Attribute  name="Country" keyColumn="ID" columnName="LEVEL_3"  hasHierarchy='false'>
          </Attribute>
        </Attributes>

        <Hierarchies>
          <Hierarchy name="EntityLy" hasAll="true">
            <Level attribute="Province"/>
            <Level attribute="City"/>
            <Level attribute="Country"/>
          </Hierarchy>
        </Hierarchies>
      </Dimension>
    </Dimensions>

    <MeasureGroups>
      <MeasureGroup name="C1_FACT" table="C1_FACT">
        <Measures>
          <Measure name="金额" column="V_1" aggregator="sum" visible="true" formatString="0.########"/>
        </Measures>
        <DimensionLinks>
          <ForeignKeyLink dimension="Year" foreignKeyColumn="YEAR"/>
          <ForeignKeyLink dimension="Entity" foreignKeyColumn="ENTITY"/>
          <ForeignKeyLink dimension="Period" foreignKeyColumn="PERIOD"/>
        </DimensionLinks>
      </MeasureGroup>
    </MeasureGroups>
  </Cube>
</Schema>

抛出错误:

Exception in thread "main" mondrian.rolap.RolapSchema$MondrianSchemaException: Attribute must have a key (in Attribute 'YearName') (at line 16, column 10)

shcemal中,属性修改如下:

<Attribute  name="Id"  keyColumn="ID"  hasHierarchy='false'/>,就不报告这个错误了。(上面已经改过了,原来写的column=)

另外,上面2个红框内容要一致。否则,报错如下:

 Key attribute 'ID' is not a valid attribute of this dimension (in Dimension 'Entity') (at line 27, column

schemal写好了,olap4j query 成功。

用mdx再测试一遍:

String mdxStr = "select {[Year].Members} on columns,{[Entity].Members} on rows from 模型一";

报错:

mondrian.olap.MondrianException: Mondrian Error:The 'Entity' dimension contains more than one hierarchy, therefore the hierarchy must be explicitly specified.

修改mdx:

String mdxStr = "select {[Year].Members} on columns,{[Entity].[EntityLy].[湖北省财政厅]} on rows from 模型一";

ok!结果如下:

写4.0schemal,我是基于2个文档的:

一个是4.0官方文档

一个是Mondrian 4规范文章(网上搜的)

进一步用Query对象查询前,我们先总结一下mondrain4.0schemal。

整体结构:见官方文档的2.1 Structure of a Schema 

A cube (see <Cube>) is a named collection of dimensions and measures.

measure:

  schemal中,别名定义:可以用于用户自定义属性?

  measure当中的caption属性,可以用于返回标题?

  table中,可以加入计算列,度量定义中,可以使用计算列。

  • An attribute is a value, possessed by every fact, by which you can divide facts into subsets. For example, you might wish to break down product sales by their color, the gender of the customer, and the store in which the product was sold; color, gender, and store are all attributes.
  • A dimension is a grouping of related attributes. For example, name, gender, zip code and eye color are attributes of the customer dimension; color, weight, and manufacturer are attributes of the product dimension.

属性的 key column then <Key> and keyColumn are equivalent

<key>元素和 attribute的属性 keyColumn,是等价的,看个人偏好 ?这个没有理解,反正key就是为和数据库匹配吧,如果不写keycolum,总报错。

对这个事情没有把握?那就用foodmart数据库重新写一个schemal

4.0文档的例子,也是报错Attribute must have a key ...

文档中是:

<Attribute name="Month" column="month_of_year">

<Key>

<Column name="the_year"/>

<Column name="month_of_year"/>

</Key>

</Attribute>

修改后是:

<Attribute name="Month" keyColumn="MONTH_OF_YEAR"/>

官文中间的<key>是啥作用,不是很了解。

官文中说:

Variations in syntax between different databases is handled by specifying more than one <Key> element:

和数据库有关?

For example, if you are defining an attribute with a simple (non-composite) key you could either write

<Attribute name="A">

<Key>

<Column name="c">

</Key>

</Attribute>

or

<Attribute name="A" column="c"/>

a simple (non-composite) key 的确是这样的。

复合键的写法如下:什么情况下用复合键呢,这个问题先留着。

If the attribute has a composite key, or if you wish to use the table attribute, you have to use the nested <Key> element:

<Attribute name="A">

<Key>

 <Column table="t1" name="c1"/>

 <Column table="t2" name="c2"/>

</Key>

</Attribute>

反正都和数据库有关。

attribute是什么意思呢,对我们的应用而言,它是必须的吗 我3.0的schemal没有写一个attribute呢。这个好像是3.0和4.0的一个明显不同的的地方。

官文推荐先写attribute,attribute的先后顺序也是查询结果的先后顺序?

看看文档的解释:

Parent element Attribute Equivalent nested element Description
<Attribute> keyColumn <Key> Column(s) that comprise the key of this attribute.构成该属性关键字的列(数据库当中的字段)。
<Attribute> nameColumn <Name> Column that defines the name of members of this attribute. If not specified, the attribute key is used.定义此属性成员名称的列。如果未指定,则使用属性键。Column就是数据库字段名?
<Attribute> orderByColumn <OrderBy> Column(s) that define the order of members. If not specified, the attribute key is used.
<Attribute> captionColumn <Caption> Column that forms the caption of members. If not specified, the attribute name is used.
<Measure> column <Arguments> Column(s) that are the arguments to this measure. (When this measure is implemented by generating a SQL expression, these columns become the argument to the SQL aggregate function.)
<Table> keyColumn <Key> Column(s) that form this Table's key.
<Link> foreignKeyColumn <ForeignKey> Column(s) that form a foreign key from this Link's referencing table to its referenced table.
<ForeignKeyLink> foreignKeyColumn <ForeignKey> Column(s) that form a foreign key from a measure group's fact table to a dimension table.

keyColumn与nameColumn:我理解都是数据库字段,区别在于,一个是key column,一个就是这个属性的column

Attribute name must be specified 这个错误的解决:

RolapSchema$MondrianSchemaException: Attribute name must be specified. (Name can only be omitted when key contains a single column.) (in Attribute 'Province')

原因是我的配置文件:

          <Attribute  name="Province" column="LEVEL_1" hasHierarchy='true'>
           <Key>
              <Column name="ID"></Column>
              <Column name="LEVEL_1"></Column>
            </Key>
        </Attribute>

测试了三种写法,都可以解决这个报错:

          <!--以下写法逻辑上是否是错误的?-->
          <!--方法1-->
<!--          <Attribute  name="Province" keyColumn="LEVEL_1" hasHierarchy='true'>
          </Attribute>-->
          <!--方法2-->
           <!-- <Attribute  name="Province"  keyColumn="ID" columnName="LEVEL_1" hasHierarchy='true'/>-->
          <!--方法3-->
          <Attribute  name="Province"  column="LEVEL_1" hasHierarchy='true'>
            <Key>
              <Column table="C1_DIM_ENTITY" name="ID"/>
              </Key>
          </Attribute>

keyColumn到底绑定那个列呢,我感到有2种选择,实际出了问题再调整不迟,反正不是key 就是colum。,我目前的看法是:用key可以在数据库中确认唯一一条记录。

Atrr元素的columnName、column有啥区别呢,没明白?问题先留着。

Inherited attributes

Hierarchy是层次结构的重点:

By default, every hierarchy contains a top level called '(All)', which contains a single member called '(All {hierarchyName})'. This member is parent of all other members of the hierarchy, and thus represents a grand total.

默认情况下,每个层次结构都包含一个名为'(All)'的顶级,其中包含一个名为'(All {hierarchyName})'的成员。 该成员是层次结构中所有其他成员的父成员,因此代表总计。

If the <Hierarchy> element has hasAll="false", the 'all' level is suppressed. The default member of that dimension will now be the first member of the first level; for example, in a Time hierarchy, it will be the first year in the hierarchy. Changing the default member can be confusing, so you should generally use hasAll="true".

借用google翻译:

如果<Hierarchy>元素具有hasAll =“false”,则“全部”级别将被抑制。 该维度的默认成员现在将是第一级别的第一个成员; 例如,在时间层次结构中,它将是层次结构中的第一年。 更改默认成员可能会造成混淆,因此通常应使用hasAll =“true”。

You can also set the default member of a hierarchy explicitly. The defaultMember attribute should be the fully-qualified name of the default member.

<Hierarchy name="Yearly" hasAll="false" defaultMember="[Time].[1997].[Q1].[1]">

...

</Hierarchy>

When specified in this way, the default member can even be a calculated member.

这个对我们有点用,财务上经常有期初、期末的概念:

先动手在schemal中增加一段配置

      <Dimension  table="C1_DIM_PERIOD"  key="Id">
        <Attributes>
          <Attribute  name="Id"  keyColumn="ID"  />
          <Attribute  name="Year"  keyColumn="YEAR" />
          <Attribute  name="Quarter"  keyColumn="QUARTER" />
          <Attribute  name="Month"  keyColumn="MONTH" />
        </Attributes>
        <Hierarchy name="期间" hasAll="true" >
          <Level attribute="Year"/>
          <Level attribute="Quarter"/>
          <Level attribute="Month"/>
        </Hierarchy>
      </Dimension>

运行测试,报错:

Exception in thread "main" java.lang.NullPointerException
	at mondrian.olap.Util.quoteMdxIdentifier(Util.java:490)
	at mondrian.rolap.RolapSchemaLoader.getOrCreateDimension(RolapSchemaLoader.java:2703)

维度中添加:

再运行,报错:

.RolapSchema$MondrianSchemaException: table 'C1_DIM_PERIOD' not found (in Dimension 'Period') (at line 27, column 6)

检查,dimession有table属性,再看发现问题,修改如下:

  <PhysicalSchema>
    <Table name="C1_FACT"/>
    <Table name="C1_DIM_YEAR"/>
    <Table name="C1_DIM_ACCOUNT"/>
    <Table name="C1_DIM_ENTITY"/>
    <Table name="C1_DIM_PERIOD"/>
  </PhysicalSchema>

PhysicalSchema中增加C1_DIM_PERIOD的说明。

再运行,ok!

修改dimession:

        <Hierarchy name="Period" hasAll="false" defaultMember="[Period].[全年合计].[4季].[12]" >
          <Level attribute="Year"/>
          <Level attribute="Quarter"/>
          <Level attribute="Month"/>
        </Hierarchy>

修改了期间的默认值? 有什么用途,后面再说。

ps1:关于uniqueMembers的设置

uniqueMembers属性用于优化SQL生成。如果你已经知道在维表中level列的值在这个层次的父级是唯一的,可以设置uniqueMembers=”true”,否则设置为"false”。例如时间维[Year].[Month]在[Month]这个level,应该设置uniqueMembers=”false”,因为同样的月可以出现在不同的年。在另一方面,假设有[Product Class].[Product Name]层次,你可以确保[Product Name]是唯一的,就可以设置uniqueMembers=”true”。如果并不能确定,则先设置为false。一般在最顶级,经常是设置为true,因为没有父层次。

引用自:https://blog.csdn.net/wonder4/article/details/4833641 

ps2:level,到层次根有同样距离层次的成员的集合。

ps3:包含type属性的Level,值可以设置为String,Integer,Numeric,Boolean,Date,Time和Timestamp。默认是Numeric,因为主键列一般为数值类型。如果类型不同,Mondrian需要知道正确的类型以便生成SQL,例如String值会生成用单引号包含的语句.

我一直没有用type.mondrian3好像用的多,是不是因为现在的level都是引用的attribute?
 

mondrian4时间维度:

MDX相关时间的函数:

  • ParallelPeriod([level[, index[, member]]])
  • PeriodsToDate([level[, member]])
  • WTD([member])
  • MTD([member])
  • QTD([member])
  • YTD([member])
  • LastPeriod(index[, member])

ps:schemal中,表名、数据库列名全部是大写(oracle的原因);

schemal中,属性名称一般是首字母大写,其余小写。

本文结尾:我针对非税开票明细再写一个schemal:

事实表:fact_col_trade_detail,记录开票信息明细表,这个表记录了松滋2009年到2017年间全部开票信息。

我们只分析维度只选取收费项目、时间,度量维只选择金额、笔数,考虑到这个表本记录的事明细数据,每条记录就是一个项目一次收费情况,可以把笔数看成退化维度? 

不过,我这里先把这个也看成一个度量,增加一个字段no,  执行update fact_col_trade_detail t set t.no=1。

接下来,我来准备项目维度:

项目维度:维度表是: dim_chargeproject

时间维度:有2种思路:

一个参照foodmart例子,构建时间维度;

另外一个是把时间拆分为年度、期间2个维度;我们分别实现这2种维度:

dim_date:这个维度标中,最小日期是2005年,最大日期是2020年。

事实表中CHARGEDATE_KEY 与datakey相应。

另外一个时间维度体系是年度、与期间:这里先只搞个年度维度表DIM_YEAR_COLTRADE:和事实表中的year_key相关联。

下面是schemal:

<?xml version="1.0" encoding="UTF-8"?>
<Schema name="OlapSchema" metamodelVersion="4.0">

  <PhysicalSchema>
    <Table name="FACT_COL_TRADE_DETAIL">
    </Table>

    <Table name="DIM_CHARGEPROJECT">
      <Key>
        <Column name='PROJECTKEY'/>
      </Key>
    </Table>

    <Table name="DIM_DATE">
      <Key>
        <Column name='DATEKEY'/>
      </Key>
    </Table>
    <Table name="DIM_YEAR_COLTRADE">
      <Key>
        <Column name='YEARKEY'/>
      </Key>
    </Table>
  </PhysicalSchema>

  <Cube name="Col_trade_detail" defaultMeasure="金额">


    <Dimensions>

      <Dimension name="Year"  table="DIM_YEAR_COLTRADE" key='Year_key' >
        <Attributes>
          <Attribute name='Year_key' keyColumn='YEARKEY' hasHierarchy='false'/>
          <Attribute name='YearString' keyColumn='YEAR' hasHierarchy='false'/>
          <Attribute name='Yearname' keyColumn='YEARNAME' hasHierarchy='false'/>
        </Attributes>
        <Hierarchies>
          <Hierarchy name='YearLy' allMemberName='All Year'>
            <Level attribute='Yearname'/>
          </Hierarchy>
        </Hierarchies>
      </Dimension>
      <Dimension name='Time' table='DIM_DATE' type='TIME' key='Time Id'>
      <Attributes>
        <Attribute name='Year' keyColumn='THE_YEAR' levelType='TimeYears' hasHierarchy='false'/>
        <Attribute name='Quarter' levelType='TimeQuarters' hasHierarchy='false'>
          <Key>
            <Column name='THE_YEAR'/>
            <Column name='DATEOFQUATER'/>
          </Key>
          <Name>
            <Column name='DATEOFQUATER'/>
          </Name>
        </Attribute>
        <Attribute name='Month' levelType='TimeMonths' hasHierarchy='false'>
          <Key>
            <Column name='THE_YEAR'/>
            <Column name='MONTH_OF_YEAR'/>
          </Key>
          <Name>
            <Column name='MONTH_OF_YEAR'/>
          </Name>
        </Attribute>
<!--        <Attribute name='Week' levelType='TimeWeeks' hasHierarchy='false'>
          <Key>
            <Column name='the_year'/>
            <Column name='week_of_year'/>
          </Key>
          <Name>
            <Column name='week_of_year'/>
          </Name>
        </Attribute>-->
        <Attribute name='Day' levelType='TimeDays' hasHierarchy='false'>
          <Key>
            <Column name='DATEKEY'/>
          </Key>
          <Name>
            <Column name='DAY_OF_MONTH'/>
          </Name>
          <OrderBy>
            <Column name='DATEKEY'/>
          </OrderBy>
        </Attribute>
        <Attribute name='Month Name' hasHierarchy='false'>
          <Key>
            <Column name='THE_YEAR'/>
            <Column name='MONTH_OF_YEAR'/>
          </Key>
          <Name>
            <Column name='THE_MONTH'/>
          </Name>
        </Attribute>
        <Attribute name='Date' keyColumn='FULLDATE' hasHierarchy='false'/>
        <Attribute name='Time Id' keyColumn='DATEKEY' hasHierarchy='false'/>
      </Attributes>

        <Hierarchies>
          <Hierarchy name='Time' hasAll='false'>
            <Level attribute='Year'/>
            <Level attribute='Quarter'/>
            <Level attribute='Month'/>
          </Hierarchy>
        </Hierarchies>

      </Dimension>

      <Dimension name="Account" table="DIM_CHARGEPROJECT"  key="Projectkey">
        <Attributes>
          <Attribute  name="Projectkey"  keyColumn="PROJECTKEY" hasHierarchy='false'>
          </Attribute>
          <Attribute name='Level1projectname'  hasHierarchy='false'>
            <Key>
              <Column name='LEVEL1PROJECTCODE'/>
            </Key>
            <Name>
              <Column name='LEVEL1PROJECTNAME'/>
            </Name>
          </Attribute>
          <Attribute name='Level2projectname'  hasHierarchy='false'>
            <Key>
              <Column name='LEVEL1PROJECTCODE'/>
              <Column name='LEVEL2PROJECTCODE'/>
            </Key>
            <Name>
              <Column name='LEVEL2PROJECTNAME'/>
            </Name>
          </Attribute>
          <Attribute name='Level3projectname'  hasHierarchy='false'>
            <Key>
              <Column name='LEVEL1PROJECTCODE'/>
              <Column name='LEVEL2PROJECTCODE'/>
              <Column name='LEVEL3PROJECTCODE'/>
            </Key>
            <Name>
              <Column name='LEVEL3PROJECTNAME'/>
            </Name>
          </Attribute>
          <Attribute name='Level4projectname'  hasHierarchy='false'>
            <Key>
              <Column name='LEVEL1PROJECTCODE'/>
              <Column name='LEVEL2PROJECTCODE'/>
              <Column name='LEVEL3PROJECTCODE'/>
              <Column name='LEVEL4PROJECTCODE'/>
            </Key>
            <Name>
              <Column name='LEVEL4PROJECTNAME'/>
            </Name>
          </Attribute>
          <Attribute name='Level5projectname'  hasHierarchy='false'>
            <Key>
              <Column name='LEVEL1PROJECTCODE'/>
              <Column name='LEVEL2PROJECTCODE'/>
              <Column name='LEVEL3PROJECTCODE'/>
              <Column name='LEVEL4PROJECTCODE'/>
              <Column name='LEVEL5PROJECTCODE'/>
            </Key>
            <Name>
              <Column name='LEVEL5PROJECTNAME'/>
            </Name>
          </Attribute>
          <Attribute name='Level6projectname'  hasHierarchy='false'>
            <Key>
              <Column name='LEVEL1PROJECTCODE'/>
              <Column name='LEVEL2PROJECTCODE'/>
              <Column name='LEVEL3PROJECTCODE'/>
              <Column name='LEVEL4PROJECTCODE'/>
              <Column name='LEVEL5PROJECTCODE'/>
              <Column name='LEVEL6PROJECTCODE'/>
            </Key>
            <Name>
              <Column name='LEVEL6PROJECTNAME'/>
            </Name>
          </Attribute>
          <Attribute name='Level7projectname' hasHierarchy='false'>
            <Key>
              <Column name='LEVEL1PROJECTCODE'/>
              <Column name='LEVEL2PROJECTCODE'/>
              <Column name='LEVEL3PROJECTCODE'/>
              <Column name='LEVEL4PROJECTCODE'/>
              <Column name='LEVEL5PROJECTCODE'/>
              <Column name='LEVEL6PROJECTCODE'/>
              <Column name='LEVEL7PROJECTCODE'/>
            </Key>
            <Name>
              <Column name='LEVEL7PROJECTNAME'/>
            </Name>
          </Attribute>
        </Attributes>

        <Hierarchies>
          <Hierarchy name='Account_L' allMemberName='All Account' >
            <Level attribute="Level1projectname"/>
            <Level attribute="Level2projectname"/>
            <Level attribute="Level3projectname"/>
            <Level attribute="Level4projectname"/>
            <Level attribute="Level5projectname"/>
            <Level attribute="Level6projectname"/>
            <Level attribute="Level7projectname"/>
          </Hierarchy>
        </Hierarchies>
      </Dimension>
    </Dimensions>

    <MeasureGroups>
      <MeasureGroup name="FACT_COL_TRADE_DETAIL" table="FACT_COL_TRADE_DETAIL">
        <Measures>
          <Measure name="金额" column="AMT" aggregator="sum" visible="true" formatString="0.########"/>
        </Measures>
        <DimensionLinks>
          <ForeignKeyLink dimension="Year" foreignKeyColumn="YEAR_KEY"/>
          <ForeignKeyLink dimension="Account" foreignKeyColumn="CHARGEPROJECT_KEY"/>
          <ForeignKeyLink dimension="Time" foreignKeyColumn="AUDITDATE_KEY"/>
        </DimensionLinks>
      </MeasureGroup>
    </MeasureGroups>
  </Cube>
</Schema>

参考文档:

https://blog.csdn.net/joe192/article/details/88966590

ps:

上一节:部署foodmart例子

下一节:olap4j入门

 

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

猜你喜欢

转载自blog.csdn.net/wh_xia_jun/article/details/90200178