Download as pdf or txt
Download as pdf or txt
You are on page 1of 9

SpagoBI WhatIf Engine

Giulio Gavardi
2016/03/30 12:12
spagobi_server - SpagoBI WhatIf Engine

Table of Contents
Document Template ................................................................................................................................................................... 3
Schema Structure for the Whatif scenario ................................................................................................................................. 4
Writeback ................................................................................................................................................................................... 6
SQL server ................................................................................................................................................................................. 8
XMLA Connection .................................................................................................................................................................... 8
Use analytical driver into schema definition .............................................................................................................................. 9

Page 2 - last modified by Giulio Gavardi on 2016/03/30 12:12


spagobi_server - SpagoBI WhatIf Engine

The SpagoBIWhatIfEngine is the brand new SpagoBI OLAP engine with writeback capabilities, based on the popular Mondrian
OLAP engine.

• Document Template
• Schema Structure for the Whatif scenario
• Writeback
• SQL server
• XMLA Connection
• Use analytical driver into schema definition

Document Template
The template is very similar to the one of Jpivot http://wiki.spagobi.org/xwiki/bin/view/spagobi_server/JPivot

Here an example of the template:


<?xml version="1.0" encoding="UTF-8"?>
<olap>
  <cube reference= "Mondrian_what_if_mysql" />
 
  <MDXquery>
  SELECT {[Measures].[Store Sales]} ON COLUMNS, {[Product].[Food]} ON ROWS FROM [Sales_V]
  WHERE CrossJoin([Version].[0], [Region].[Mexico Central])
  </MDXquery>
  <MDXMondrianQuery>
  SELECT {[Measures].[Store Sales]} ON COLUMNS, {[Product].[Food]} ON ROWS FROM [Sales_V]
  WHERE CrossJoin([Version].[0], [Region].[Mexico Central])
  </MDXMondrianQuery>
 
  <SCENARIO name= "scenario" editCube= "Sales_Edit" initialVersion= "0" >
    <MEASURE>Store Sales </MEASURE>
    <MEASURE>Store Cost </MEASURE>
    <VARIABLE name= "myvariable" value= "5" />
    <VARIABLE name= "dairy_drink" value= "[Product].[Drink.Dairy]" type= "string" />
  </SCENARIO>
 
  <ALIASES>
    <DIMENSION name= "Product" alias= "P" />
    <HIERARCHY name= "TimeByQuarter" alias= "TbQ" />
    <ALIAS name= "Product.Eggs" alias= "Eggs" />
  </ALIASES>
 
  <TOOLBAR>
    <BUTTON_MDX visible= "false" menu= "true" />
    <BUTTON_FATHER_MEMBERS visible= "false" menu= "true" />
    <BUTTON_HIDE_SPANS visible= "false" menu= "true" />
    <BUTTON_SHOW_PROPERTIES visible= "false" menu= "true" />
    <BUTTON_HIDE_EMPTY visible= "false" menu= "true" />
    <BUTTON_FLUSH_CACHE visible= "true" menu= "false" />
    <BUTTON_SAVE visible= "true" menu= "false" />
    <BUTTON_SAVE_NEW visible= "true" menu= "false" />
    <BUTTON_UNDO visible= "true" menu= "false" />
    <BUTTON_VERSION_MANAGER visible= "true" menu= "false" />
    <BUTTON_EXPORT_OUTPUT visible= "true" menu= "false" />
    <BUTTON_EXPORT_XLS visible= "true" menu= "false" />  
  </TOOLBAR>
 
</olap>

The tags are:

• <cube reference="SCHEMA"/>
The schema for the cube. The value of the attribute reference is the label of the schema saved in the Schema catalogue 
• <MDXMondrianQuery>

Page 3 - last modified by Giulio Gavardi on 2016/03/30 12:12


spagobi_server - SpagoBI WhatIf Engine

The MDXMondrianQuery section contains the original MDX query (the one edited via the wizard)
• <MDXquery>
The MDX section contains a variation of the original MDX query, as used by SpagoBI Engine. This version includes
parameters (if any).  
 
• <SCENARIO>
This tag should be used when the user want to perform what if analysis.
The attributes and subtags of the tag are:
° name: the name of the scenario. It’s only a label and it’s not used by the engine..
° editCube: the name of the table that contains contains the edited values (see the structure of the schema section)
° <MEASURE>MEASURE NAME </MEASURE>: there could be 0 or n tag measure. They are the names of the

editable measures. If no tag measure is defined than all the measures are editable.
° <VARIABLE name="var" value="5"/>: variables that can be used in the editing formulas. The

properties of the tag variable are


· Name: with the name of the variable
· Value: the value of the variable
· Type: the return type it can be string, int e double. The default is double.
Formula Example: = 100+var . The value of this formula is 105.
The String type can be used referring to members. For example <VARIABLE name="PD"
value="[Product].[Drink.Dairy]" type="string"/>
• <ALIASES>
It contains a list of alias. The possible sub tags are:
° DIMENSION: for dimension placeholders (for example Product in Product.Drink)
° HIERARCHY: for hierarchy  placeholders (for example TimeByDay in Time.TimeByDay.Year)
° ALIAS: a generic placeholder (for example Time.TimeByDay.Year)

The attributes of these tags are


· Name: the value of the alias
· Alias: the name of the alias
• <TOOLBAR>
Contains the list of buttons
Each subtag is a visible button. In the previous example you can see the list off all the possible buttons.
The order of the buttons in the toolbar is the same of the buttons definition in the template.
If no tag <toolbar> is defined all buttons will be displayed.
The order of the buttons inside the tag toolbar is the same order

Schema Structure for the Whatif scenario


The what if analysis is the capability to change the values of the cells of the cube, and see how these changes impact in the rest
of the cube.. After some interaction with the cube, the user can save the new modified data.. Of course it’s not a good idea to
modify the data of the DWH, so it’s necessary to make some change in the schema to allow this modification without touching
the original DWH..

Changes in the dwh


The first thing to do is to create a new table in the db that stores the edited data. The user changes the values of the
cube, so we need to create a new table with a structure similar to the analysis cube, plus a new table (wbversion) that will
contain analysis versions definition.
The structure of the new fact table should :

• contain all the foreign key to the dimension (all the ones visible in the cube)
• contain all the editable measures
• contain a new numeric column that is a foreign key referencing the version table.

Here an example where the cube is sales_fact_1998 and the new table is sales_fact_1998_virtual

Page 4 - last modified by Giulio Gavardi on 2016/03/30 12:12


spagobi_server - SpagoBI WhatIf Engine

sales_fact_1998_virtual table should be initialized with the same data contained in sales_fact_1998 plus 0 as version; the
wbversion table should be initialized with one record with wbversion = 0 and a name and a description for "Original values".

Changes in the mondrian schema


Now you should map the new tables in the mondrian schema.
In order to merge the fact table and the table with the editable measure we create a virtual cube. A virtual cube is a
special cube where the values are the result of the join of other cubes. In our case the join keys are the dimensions.
The action to performs in the mondrian schema are:

• create a new "Version" dimension:


<Dimension name= "Version" >
  <Hierarchy hasAll= "false" primaryKey= "wbversion" >
    <Table name= "wbversion" />
    <Level name= "Version" column= "wbversion" uniqueMembers= "true" captionColumn= "version_name" />
  </Hierarchy>
</Dimension>
• create the mapping of the editable cube (in our example the table sales_fact_1998_virtual)
<Cube name= "Sales_Edit" >
  <Table name= "sales_fact_1998_virtual" />
  <DimensionUsage name= "Product" source= "Product" foreignKey= "product_id" />
  <DimensionUsage name= "Region" source= "Region" foreignKey= "store_id" />   
  <DimensionUsage name= "Customers" source= "Customers" foreignKey= "customer_id" />   
  <DimensionUsage name= "Version" source= "Version" foreignKey= "wbversion" />
  <Measure name= "Store Sales" column= "store_sales" aggregator= "sum"        formatString= "#,###.00" />
</Cube>
The name of the cube ("Sales_Edit") is the value of the editCube attribute of the tag scenario in the template.
The name of the dimension Version must be exactly "Version"!!
• create the virtual cube
The virtual cubes contains the mapping of the columns:
<VirtualCube name= "Sales_V" >
  <CubeUsages>
    <CubeUsage cubeName= "Sales_Edit" ignoreUnrelatedDimensions= "true" />
    <CubeUsage cubeName= "Sales" ignoreUnrelatedDimensions= "true" />
  </CubeUsages>
  <VirtualCubeDimension cubeName= "Sales" name= "Customers" />
  <VirtualCubeDimension cubeName= "Sales" name= "Product" />
  <VirtualCubeDimension cubeName= "Sales" name= "Region" />
  <VirtualCubeDimension cubeName= "Sales_Edit" name= "Customers" />
  <VirtualCubeDimension cubeName= "Sales_Edit" name= "Product" />
  <VirtualCubeDimension cubeName= "Sales_Edit" name= "Region" />
  <VirtualCubeDimension cubeName= "Sales_Edit" name= "Version" />
  <VirtualCubeMeasure cubeName= "Sales" name= "[Measures].[Unit Sales Original]" visible= "false" />
  <VirtualCubeMeasure cubeName= "Sales" name= "[Measures].[Sales Count Original]" visible= "false" />
  <VirtualCubeMeasure cubeName= "Sales_Edit" name= "[Measures].[Store Sales]" visible= "true" />
  <VirtualCubeMeasure cubeName= "Sales_Edit" name= "[Measures].[Store Cost]" visible= "true" />
  <CalculatedMember name= "Sales Count" dimension= "Measures" >

Page 5 - last modified by Giulio Gavardi on 2016/03/30 12:12


spagobi_server - SpagoBI WhatIf Engine

    <Formula>VALIDMEASURE([Measures].[Sales Count Original]) </Formula>


  </CalculatedMember>
  <CalculatedMember name= "Unit Sales" dimension= "Measures" >
    <Formula>VALIDMEASURE([Measures].[Unit Sales Original]) </Formula>
  </CalculatedMember>
</VirtualCube>
In the virtual cube you should specify:
° the list of cubes to be joined (CubeUsages).
° The list of the dimensions of the cube (as you can see it contains all the common dimensions, plus the Version that

belongs only to the editable cube)


° The list of the measures. You can perceive that there is a calculated member for the measure Sales Count Original

(Sales Count Original is the name of a measure in the Sales cube). This is a trick for the not editable measures.
This type of measure lives only in the DWH cube and not in the editable cube. This cause that the engine doesn’t
know how to give a value for these measures for the different values of the Version dimension (remember that
only the editable cube has the Version dimension). The calculated field solve this problem propagating the same
version of the not editable (and versionable) measure for all the version.
Now all the MDX queries should be performed in the virtual cube.

Writeback
The SpagoBIWhatIfEngine has write-back capabilities, i.e. you can edit the value of a cell and observe the results.

   
 

Keep in mind that changes are stored in memory: if you want to persist modifications into the database, you have to click on

the commit     button.

When modifying a cell, since this cell may contain an aggregate value on several dimensional members, the new value must
be divided into all the underlying members, untill leaves are reached.

The What-If engine, at the moment (SpagoBI 5.0.0), supports only one propagation algorithm, that does not modify the
weight of sibling children members. When a cell with X value is modified and Y value is set as new value, this formula is
applied to the children cells:

<new cell value> = <previuos cell value> * <Y> / <X>

This formula doesn't make sense when X is 0 or it doen't even exist: this is the reason why you cannot modify cell with no
value or with zero-value.

Let's look at an example: we (nearly) double the value for Drink and children cells are updated keeping the same ratio
between them:

   
 

You can modify a cell and enter a new value or a formula using a particular language that is described below.

The following arithmetic symbols are available:


+-*/()%
Example with %:
100 + 10% = 110
The formula can start with "=", but this is not mandatory.

You can also refer to members that are not included in the tuple represented by the cell being modified: let's see some
examples: suppose the cell refers to the following tuple:

Page 6 - last modified by Giulio Gavardi on 2016/03/30 12:12


spagobi_server - SpagoBI WhatIf Engine

[Measures].[ Store Sales], [Product].[Food].[ Deli], [Version].[0], [Region].[Mexico Central], [Customers].[All Customers],
[Customers].[All Customers]

you can refer to the tuple

[Measures].[Store Sales], [Product].[Food].[ Eggs], [Version].[0], [Region].[Mexico Central], [Customers].[All Customers],


[Customers].[All Customers]

with just 

Product.Eggs

and at the same time to the tuple

[Measures].[ Unit Sales], [Product].[Food].[ Eggs], [Version].[0], [Region].[Mexico Central], [Customers].[All Customers],
[Customers].[All Customers]

with:

Product.Eggs;Measures.Unit Sales

When referring to external members (members that are not included in the tuple of the cell), remember that you can get only
refer to members on the same level of the internal ones.

The syntax is
<dimension's name>.<member's name> or [<dimension's name>].[<member's name>]
or, in case you are using another hierarchy
<dimension's name>.<hierarchy's name>.<member's name> or [<dimension's name>].[<hierarchy's name>].[<member's
name>]
and you can concatenate different members with ";".

You can also refer to members that are on the same level but they are not sibling members: suppose that, for example, the
cell's tuple is
[Measures].[Store Sales], [Product].[ Food].[ Deli], [Version].[0], [Region].[Mexico Central], [Customers].[All Customers],
[Customers].[All Customers]

you can refer to the tuple

[Measures].[Store Sales], [Product].[ Drink].[ Alcoholic Beverages], [Version].[0], [Region].[Mexico Central], [Customers].
[All Customers], [Customers].[All Customers]

just with:

[Product].[Drink.Alcoholic Beverages]

Another example: form 

[Measures].[Store Sales], [Product].[ Food].[ Deli].[ Meat], [Version].[0], [Region].[Mexico Central], [Customers].[All
Customers], [Customers].[All Customers]

to 

[Measures].[Store Sales], [Product].[ Drink].[ Alcoholic Beverages].[ Beer and Wine], [Version].[0], [Region].[Mexico
Central], [Customers].[All Customers], [Customers].[All Customers]

the expression is 

[Product].[Drink.Alcoholic Beverages.Beer and Wine]

Note that the last part of the expression is the portion of the path to the target member that differs from the path of the cell's
member.

Variables

When modifying an OLAP analysis, you normally are operating in a scenario that might have variables (the inflation rate, for
example, or the number of employees) that you can define and use when modifying a cell's value.
The definition of the scenario is provided within the template of the document:

<SCENARIO name="<name of the scenario>" editCube="Sales_Edit">


 <VARIABLE name="<name of the variable>" value="<value>" type="<integer/double/string>"/>
 ...............
</SCENARIO>

Page 7 - last modified by Giulio Gavardi on 2016/03/30 12:12


spagobi_server - SpagoBI WhatIf Engine

In case the variable is an integer or double value, is it considered just as a static number; instead,  if it is a string, it is
considered to be the reference to one or more dimensional members. This reference is intented to be relative to the cell being
modified and it must be specified with the syntax described above, for example:

<SCENARIO name="My scenario" editCube="Sales_Edit">


 <VARIABLE name="eggs" value="[Product].[Product.Eggs]" type="string"/>
</SCENARIO>

Aliases 

A part from variables, you can also use aliases when editing an expression.
The definition of the aliases is contained into the document's template:

<ALIASES>
 <DIMENSION name="Product" alias="P"/>
 <HIERARCHY name="Time Weekly" alias="W"/>
 <ALIAS name="Product.Eggs" alias="Eggs"/>
</ALIASES>
As shown in the above example, an alias can refer to:

• a dimension: e.g. P.Eggs is resolved as Product.Eggs;


• a hierarchy:  W is resolved as Time Weekly;
• a reference one or more dimensional members: Eggs is resolved as Product.Eggs; the reference is intended to be relative
 to the cell being modified and it must be specified with the syntax described above (same as variables).

It is possible also to refer to a hierarchy in one dimension with a single alias: in the following example, TW is resolved as
Time.Time Weekly:

<ALIASES>
 <DIMENSION name="Time.Time Weekly" alias="TW"/>
</ALIASES> the version.

Now all the MDX queries should be performed in the virtual cube.

SQL server
If your datasource is the RDBM SQL Server, in the JDBC Url you should add the prefix jdbc. to the property databaseName.
So the URL should be something like
jdbc:sqlserver://USER\MSSQLSERVER2; jdbc.databaseName =TEST_DWH

XMLA Connection
If you are connecting to a XMLA server you should add the end point of the server into the document template.
Technically specking you should add the tag <xmlaserver>. The possible children are the the url of the server and the list of
properties required for the connection.

Example

<?xml version="1.0" encoding="UTF-8"?>


<olap>
<xmlaserver>
<url>http://111.111.111.111:8000/xml/soap/xmla </url>
<user>user </user>
<password>password </password>
</xmlaserver>
<MDXquery>
SELECT [DIM1] ON ROWS, [Measures].[M1] ON COLUMNS FROM [CUBE]
</MDXquery>
<MDXMondrianQuery>
SELECT [DIM1] ON ROWS, [Measures].[M1] ON COLUMNS FROM [CUBE]
</MDXMondrianQuery>
</olap>

Page 8 - last modified by Giulio Gavardi on 2016/03/30 12:12


spagobi_server - SpagoBI WhatIf Engine

Use analytical driver into schema definition


From SpagoBI 5.1 version is possible use analytical driver into the dimensions' definition, directly into the cube:

Example

<Dimension name= "Product" foreignKey= "product_id" >


  <Hierarchy hasAll= "true" allMemberName= "All Products" primaryKey= "product_id" >
<View alias= "Product" >
  <SQL dialect= "generic" >
select
 p.product_family as product_family,
 p.product_id as product_id,
 p.product_name as product_name,
 p.brand_name as brand_name,
 p.product_subcategory as product_subcategory,
 p.product_category as product_category,
 p.product_department as product_department
from
 product as p
where
 p.product_family = '$P{filter}'
  </SQL>
</View>
<Level name= "Product Family" column= "product_family" uniqueMembers= "false" />
<Level name= "Product Department" column= "product_department" uniqueMembers= "false" />
<Level name= "Product Category" column= "product_category" uniqueMembers= "false" />
<Level name= "Product Subcategory" column= "product_subcategory" uniqueMembers= "false" />
<Level name= "Brand Name" column= "brand_name" uniqueMembers= "false" />
<Level name= "Product Name" column= "product_name" uniqueMembers= "true" />
  </Hierarchy>
</Dimension>

Page 9 - last modified by Giulio Gavardi on 2016/03/30 12:12

You might also like