MicroStrategy ONE
Using OLAP Functions
You can better understand how Intelligence Server computes OLAP functions by observing several examples based on the following properties:
- Window size
- BreakBy
- SortBy
- NULL handling
- Tie handling
There are two examples for each subsection, comparing the SQL syntax when the database performs the OLAP function calculations with the one when the Intelligence Server performs the computation.
Window Size in Moving Functions
For this example, define metric M1A as Sum(Revenue){~+}
. Then create an OLAP metric called OM1, that is defined as
MovingAvg <BreakBy = {Category}, SortBy = (Value)>([M1A],5).
OM1computes the moving average of M1A with a window size of 5. The OLAP metric is computed after it is sorted by the value of M1A in ascending order. Moreover, the computation restarts for every category.
Now, put the attributes Category and Item on the Row axis and the above metrics on the Column axis. Run this report with an empty filter against a database that does not support OLAP functions (in this case Microsoft Access), the following SQL is generated:
Report 5A (MicroStrategy OLAP function - window size) - Microsoft Access
Pass0 - Duration: 0:00:00.60 select a13.[CATEGORY_ID] AS CATEGORY_ID, max(a14.[CATEGORY_DESC]) AS CATEGORY_DESC, a11.[ITEM_ID] AS ITEM_ID, max(a12.[ITEM_NAME]) AS ITEM_NAME, sum(a11.[TOT_DOLLAR_SALES]) AS WJXBFS1 from [ITEM_MNTH_SLS] a11, [LU_ITEM] a12, [LU_SUBCATEG] a13, [LU_CATEGORY] a14 where a11.[ITEM_ID] = a12.[ITEM_ID] and a12.[SUBCAT_ID] = a13.[SUBCAT_ID] and a13.[CATEGORY_ID] = a14.[CATEGORY_ID] group by a13.[CATEGORY_ID], a11.[ITEM_ID] Pass1 - Duration: 0:00:00.01 [An Analytical SQL]
Alternatively, if you execute the above report against a database that does support OLAP computations (in this case Oracle 9i), then the following SQL is generated:
Report 5B (DB OLAP Function - Window Size) - Oracle 9i
Pass0 - Duration: 0:00:10.15 select a13.CATEGORY_ID CATEGORY_ID, a14.CATEGORY_DESC CATEGORY_DESC, a11.ITEM_ID ITEM_ID, a12.ITEM_NAME ITEM_NAME, sum((a11.QTY_SOLD * (a11.UNIT_PRICE - a11.DISCOUNT))) WJXBFS1, avg(sum((a11.QTY_SOLD * (a11.UNIT_PRICE - a11.DISCOUNT)))) over(partition by a13.CATEGORY_ID order by sum((a11.QTY_SOLD * (a11.UNIT_PRICE - a11.DISCOUNT))) asc rows 4 preceding) WJXBFS2 from ORDER_DETAIL a11, LU_ITEM a12, LU_SUBCATEG a13, LU_CATEGORY a14 where a11.ITEM_ID = a12.ITEM_ID and a12.SUBCAT_ID = a13.SUBCAT_ID and a13.CATEGORY_ID = a14.CATEGORY_ID group by a13.CATEGORY_ID, a14.CATEGORY_DESC, a11.ITEM_ID, a12.ITEM_NAME
The following example shows how the Intelligence Server computes OLAP functions when the database does not support OLAP functions. The Intelligence Server retrieves all components: the input metric, BreakBy parameter, and SortBy parameter. In the above examples, since the SortBy parameter setting is by Value, it is sufficient to bring back just the input metric (WJXBFS1).
BreakBy in OLAP Functions
In the Intelligence Server, the BreakBy parameter is only available at the attribute level. In other words, you can start over certain computations of OLAP functions when a part of the metric belongs to a different attribute element.
In the previous example (window size), there is an OLAP function with Category in the BreakBy parameter. If the Analytical Engine computes the OLAP function, Intelligence Server must select this attribute in the select
clause. If the database computes the OLAP function, then this attribute must also be in the partition by
clause.
Attributes in the BreakBy parameter of an OLAP metric are always applied, meaning that they are always in the Select
clause, and if the database computes it, they are also in the Partition by
clause. This is true whether the attribute is on the template or not.
Run a report similar to the one for window size, deleting the attributes Category and Item from the template and adding Subcategory. The results for metric M1A
are completely different from the previous report because if Category and Item are not on the template, then the level of aggregation for metric M1A is replaced by Subcategory, which is on the template. On the other hand, OLAP metric OM1 must still restart the calculation (break by) for each Category and therefore remains in the appropriate Select
and Partition by
clauses. Notice that in both the SQLs below, the Intelligence Server always selects Category even though Category is not on the template.
For a database that does not support OLAP functions (in this case Microsoft Access), the following SQL is generated:
Report 6A (MicroStrategy OLAP Function <BreakBy>) - Microsoft Access
Pass0 - Duration: 0:00:00.63 select a11.[SUBCAT_ID] AS SUBCAT_ID, max(a12.[SUBCAT_DESC]) AS SUBCAT_DESC, a12.[CATEGORY_ID] AS CATEGORY_ID, sum(a11.[TOT_DOLLAR_SALES]) AS WJXBFS1 from [CITY_SUBCATEG_SLS] a11, [LU_SUBCATEG] a12 where a11.[SUBCAT_ID] = a12.[SUBCAT_ID] group by a11.[SUBCAT_ID], a12.[CATEGORY_ID] Pass1 - Duration: 0:00:00.00 [An Analytical SQL]
If the database supports computation of OLAP functions (in this example Oracle), then the following SQL is generated:
Report 6B (DB OLAP Function) - Oracle
Pass0 - Duration: 0:00:09.39 select a12.SUBCAT_ID SUBCAT_ID, a13.SUBCAT_DESC SUBCAT_DESC, a13.CATEGORY_ID CATEGORY_ID, sum((a11.QTY_SOLD * (a11.UNIT_PRICE - a11.DISCOUNT))) WJXBFS1, avg(sum((a11.QTY_SOLD * (a11.UNIT_PRICE - a11.DISCOUNT)))) over(partition by a13.CATEGORY_ID order by sum((a11.QTY_SOLD * (a11.UNIT_PRICE - a11.DISCOUNT))) asc rows 4 preceding) WJXBFS2 from ORDER_DETAIL a11, LU_ITEM a12, LU_SUBCATEG a13 where a11.ITEM_ID = a12.ITEM_ID and a12.SUBCAT_ID = a13.SUBCAT_ID group by a12.SUBCAT_ID, a13.SUBCAT_DESC, a13.CATEGORY_ID
Sorting in OLAP Functions
For OLAP functions, sorting is done before performing computations. Basically, there are two choices for the SortBy parameter setting:
- Sort by Value in Subexpression: See Reports 5B (in Report 5B (DB OLAP Function - Window Size) - Oracle 9i) and 6B (in Report 6B (DB OLAP Function) - Oracle ) for examples. Note that if the database can perform computation of OLAP functions, then the definition of the subexpression M1A displays in the
order by
clause.For example, the above reports contain: "
order by sum((a11.QTY_SOLD * (a11.UNIT_PRICE - a11.DISCOUNT))) asc
" to represent the <SortBy = Value ascending> parameter setting.
- Sort by Objects: This type of sorting can use either attributes or metrics. The following examples demonstrate the differences in processing when an attribute or metric is used.
In this example, the OLAP metric is sorted by a normal attribute (either by ID or Desc).
Create an OLAP metric defined as:
OM2 = RunningSum<BreakBy = {[Customer Region]}, SortBy = ([Customer City]@ID asc, Customer@Name dsc)>([M1A])
Then add the attributes Customer Region and Customer, and the metric OM2 to the template.
The metric OM2 is sorted by Customer City@ID in ascending order, then by Customer@Name in descending order, though the attribute Customer City is not on the template. Assume that attribute Customer is a child of the attribute Customer City, and Customer City is a child of Customer Region.
For a database that does not support OLAP functions (in this case Microsoft Access), the following SQL is generated:
Report 7A (MicroStrategy OLAP Function <SortBy>) - Microsoft Access
select a14.[CUST_REGION_ID] AS CUST_REGION_ID, a15.[CUST_REGION_NAME] AS CUST_REGION_NAME, a11.[CUSTOMER_ID] AS CUSTOMER_ID, a12.[CUST_LAST_NAME] AS CUST_LAST_NAME, a12.[CUST_FIRST_NAME] AS CUST_FIRST_NAME, a12.[CUST_CITY_ID] AS CUST_CITY_ID, a11.[TOT_DOLLAR_SALES] AS WJXBFS1 from [CUSTOMER_SLS] a11, [LU_CUSTOMER] a12, [LU_CUST_CITY] a13, [LU_CUST_STATE] a14, [LU_CUST_REGION] a15 where a11.[CUSTOMER_ID] = a12.[CUSTOMER_ID] and a12.[CUST_CITY_ID] = a13.[CUST_CITY_ID] and a13.[CUST_STATE_ID] = a14.[CUST_STATE_ID] and a14.[CUST_REGION_ID] = a15.[CUST_REGION_ID] [An Analytical SQL]
If the database supports computation of OLAP functions (in this example Oracle 9i), the following SQL is generated:
Report 7B (DB OLAP Function <SortBy>) - Oracle
Pass0 - Duration: 0:00:15.00 select a15.CUST_REGION_ID CUST_REGION_ID, a16.CUST_REGION_NAME CUST_REGION_NAME, a12.CUSTOMER_ID CUSTOMER_ID, a13.CUST_LAST_NAME CUST_LAST_NAME, a13.CUST_FIRST_NAME CUST_FIRST_NAME, a13.CUST_CITY_ID CUST_CITY_ID, sum(sum(a11.ORDER_AMT)) over(partition by a15.CUST_REGION_ID order by a13.CUST_CITY_ID asc, a13.CUST_LAST_NAME desc, a13.CUST_FIRST_NAME desc rows unbounded preceding) WJXBFS1 from ORDER_FACT a11, LU_ORDER a12, LU_CUSTOMER a13, LU_CUST_CITY a14, LU_CUST_STATE a15, LU_CUST_REGION a16 where a11.ORDER_ID = a12.ORDER_ID and a12.CUSTOMER_ID = a13.CUSTOMER_ID and a13.CUST_CITY_ID = a14.CUST_CITY_ID and a14.CUST_STATE_ID = a15.CUST_STATE_ID and a15.CUST_REGION_ID = a16.CUST_REGION_ID group by a15.CUST_REGION_ID, a16.CUST_REGION_NAME, a12.CUSTOMER_ID, a13.CUST_LAST_NAME, a13.CUST_FIRST_NAME, a13.CUST_CITY_ID
In both SQLs, the Intelligence Server selects a13.CUST_CITY_ID, even though attribute Customer City is not on the report. In Report 7B, this attribute is also in the group by
clause. Sort by attribute Customer City@ID is done because of attribute Customer that is a child of Customer City.
In Report 7B, the SQL has to issue group by CUST_LAST_NAME and CUST_FIRST_NAME due to the sort by Customer@Name. For optimization purposes, the Intelligence Server only groups by the ID column.
There is a VLDB setting that allows you to group by non-ID columns. This VLDB setting can be set for any report that uses an OLAP metric with a sort by attribute description.
In this example, an OLAP metric is sorted by an attribute and a metric.
Create an OLAP metric defined as:
OM3 = RunningSum<BreakBy = {[Customer Region]}, SortBy = (Customer@[Last Name] desc, [M1A] asc)>([M1A])
Then add attributes Customer Region and Customer, and metric OM3 to the template. The OLAP metric OM3 is sorted by Customer Last Name and then by the metric [M1A].
For databases that do not support OLAP functions (in this case Microsoft Access), the following SQL is generated:
Report 8A (MicroStrategy OLAP Function <SortBy>) - Microsoft Access
Pass0 - Duration: 0:00:00.47 select a14.[CUST_REGION_ID] AS CUST_REGION_ID, a15.[CUST_REGION_NAME] AS CUST_REGION_NAME, a11.[CUSTOMER_ID] AS CUSTOMER_ID, a12.[CUST_LAST_NAME] AS CUST_LAST_NAME, a12.[CUST_FIRST_NAME] AS CUST_FIRST_NAME, a11.[TOT_DOLLAR_SALES] AS WJXBFS1 from [CUSTOMER_SLS] a11, [LU_CUSTOMER] a12, [LU_CUST_CITY] a13, [LU_CUST_STATE] a14, [LU_CUST_REGION] a15 where a11.[CUSTOMER_ID] = a12.[CUSTOMER_ID] and a12.[CUST_CITY_ID] = a13.[CUST_CITY_ID] and a13.[CUST_STATE_ID] = a14.[CUST_STATE_ID] and a14.[CUST_REGION_ID] = a15.[CUST_REGION_ID] and a14.[CUST_REGION_ID] in (3, 7) Pass1 - Duration: 0:00:00.06 [An Analytical SQL]
If the database supports computation of OLAP functions (in this example Oracle), the following SQL is generated:
Report 8B (DB OLAP Function <SortBy>) - Oracle
select a15.CUST_REGION_ID CUST_REGION_ID, a16.CUST_REGION_NAME CUST_REGION_NAME, a12.CUSTOMER_ID CUSTOMER_ID, a13.CUST_LAST_NAME CUST_LAST_NAME, a13.CUST_FIRST_NAME CUST_FIRST_NAME, sum(a11.ORDER_AMT) WJXBFS1, sum(sum(a11.ORDER_AMT)) over(partition by a15.CUST_REGION_ID order by a13.CUST_LAST_NAME desc, sum(a11.ORDER_AMT) desc rows unbounded preceding) WJXBFS2 from ORDER_FACT a11, LU_ORDER a12, LU_CUSTOMER a13, LU_CUST_CITY a14, LU_CUST_STATE a15, LU_CUST_REGION a16 where a11.ORDER_ID = a12.ORDER_ID and a12.CUSTOMER_ID = a13.CUSTOMER_ID and a13.CUST_CITY_ID = a14.CUST_CITY_ID and a14.CUST_STATE_ID = a15.CUST_STATE_ID and a15.CUST_REGION_ID = a16.CUST_REGION_ID and a15.CUST_REGION_ID in (7, 3) group by a15.CUST_REGION_ID, a16.CUST_REGION_NAME, a12.CUSTOMER_ID, a13.CUST_LAST_NAME, a13.CUST_FIRST_NAME
NULL Handling in OLAP Functions
When sorted by Intelligence Server, NULL is placed at the end of a list. Databases also put NULL at the end, as required by the ANSI standard.
For RunningCount or MovingCount functions, NULL is always ignored. For other computations, such as RunningSum or MovingAvg, NULL is treated as zero for the sum of values across the function parameters. This behavior is consistent for Intelligence Server and ANSI-compliant database OLAP functions.
Tie Handling in OLAP Functions
Tie Handling is related to the SortBy parameter when you sort a tie in a metric. Intelligence Server uses a Merge-Sort algorithm, which always preserves the original order retrieved from the database (via ODBC) to the Intelligence Server.
It is not known whether databases use the same sort algorithm; therefore, the Intelligence Server and database computation of OLAP functions can produce different results whenever there is a tie on the data.