I found a way to solve this requirement.
The problem consisted of three different problems
- Get subfields as year, month or ... from a timestamp
- Use a fact table column as dimension
- Use a hierarchy/multiple attributes in a fact table based dimension
I solved all three problems, as described below, but none of the solutions is a perfect in my eyes, so if you have any improvement suggestions, pls let me know in a comment below. Everything described below is for the metamodel version 4.0 and a PostgreSQL database.
1. Get subfields as year, month or ... from a timestamp
I couldn't find a integrated solution and therefor made my own.
In the Mondrian Schema you can define calculated columns for a table.
<Table name="sales" schema="reporting">
<ColumnDefs>
<CalculatedColumnDef name='store2'>
<ExpressionView>
<SQL dialect='generic'>
<Column name='store'/>
</SQL>
</ExpressionView>
</CalculatedColumnDef>
</ColumnDefs>
</Table>
Somehow mondrian allways uses generic
as dialect and therefor postgres
as dialect doesn't work. With <Column name='column'/>
you can use a column value of the same table. In the example above, it's the store
column of the sales
table.
We can use the same method to add a year, month, ... column for every subfield we want out of the timestamp.
For quarter it looks like this:
<CalculatedColumnDef name='quarter'>
<ExpressionView>
<SQL dialect='generic'>
'Q' || EXTRACT(QUARTER FROM <Column name='date'/>)
</SQL>
</ExpressionView>
</CalculatedColumnDef>
Now you only have to do this for every subfield you need.
All supported subfield from PostgreSQL: PostgreSQL - Date/Time Function EXTRACT
2. Use a fact table column as dimension
A dimension with no defined table is not possible in the mondrian schema. Some would think that the schema would just assume the fact table as default table but the mondrian schema does not.
How to solve this is not stated in the mondrian documentation. But it's just as simple as using a different link for the DimensionLinks
.
Use this link (where xy
schould be the dimension name):
<FactLink dimension="xy"/>
3. Use a hierarchy/multiple attributes in a fact table based dimension
At this point it's really confusing what Mondrian does. With only 1., 2. and a hierarchical dimension Mondrian crashes and says:
Dimension 'xy'; omits a defined key, which is only valid for degenerate dimensions with a single attribute.
That doesn't make any sense to me and the solution does make no sense at all.
Just add a key
to the dimension and a corresponding key attribute and it works. No idea why!
Use all subfields in a dimension
The Mondrian documentation does recomment to use the dimension type TIME
and the corresponding attribute levelType
's.
Out of the documentation:
Time dimensions based on year/month/week/day are coded differently in the Mondrian schema due to the MDX time related functions
For me, that made no difference at all, but still i have included it in my dimension:
<Dimension name='Time' key="Timestamp" type="TIME">
<Attributes>
<Attribute name='Timestamp' table='sales' keyColumn='slice_date' hasHierarchy="false"/>
<Attribute name='Year' table='sales' keyColumn='year' levelType="TimeYears" hasHierarchy='false'/>
<Attribute name='Quarter' table='sales' keyColumn='quarter' levelType="TimeQuarters" hasHierarchy='false'/>
<Attribute name='Month' table='sales' keyColumn='month' levelType="TimeMonths" hasHierarchy='false'/>
<Attribute name='Day' table='sales' keyColumn='day' levelType="TimeWeeks" hasHierarchy='false'/>
<Attribute name='Week' table='sales' keyColumn='week' levelType="TimeDays" hasHierarchy='false'/>
<Attribute name='Day of Week' table='sales' keyColumn='dayOfWeek' levelType="TimeWeeks" hasHierarchy='false'/>
</Attributes>
<Hierarchies>
<Hierarchy name='Monthly'>
<Level attribute='Year'/>
<Level attribute='Quarter'/>
<Level attribute='Month'/>
</Hierarchy>
<Hierarchy name='Weekly'>
<Level attribute='Year'/>
<Level attribute='Week'/>
<Level attribute='Day of Week'/>
</Hierarchy>
</Hierarchies>
</Dimension>
Now you only have to use this dimension in a cube with the, in 2. decribed, link:
<Dimensions>
<Dimension source="Time"/>
</Dimensions>
I hope this does help someone else.