Tag Archives: MDX

Same members declared in both Sub Select and Where clause of same MDX

What to make of it?

Currently I am conducting a review on all existing solutions. These solutions have seen their share of developers over the years. Hence there are several “trademarks” to be found. One such trademark threw me off a bit. It seemed as if the same method had been applied to all queries in the solution. For every expression in the where clause, there would be a similar sub select statement. So if there was a slice by [Product].[Category].&[4], there would be a Sub Select eg. ( SELECT [Product].[Category].&[4] ON COLUMNS FROM… )

I hadn’t seen this construct before, so I felt challenged to find out, if this had some purpose or it was poorly written MDX. I acknowledge, that sometimes development is rushed, and you leave behind unwanted code. But this looked as if it was written to stay. There was almost no complexity to the MDX, other than the odd construct… An example of a statement converted into Adventure Works lingo, would look something like this:

I looked up Sub Cubes in Analysis Services 2008 Unleashed, which is a ressource I would highly recommend it, if you don’t already know of it. In this book, a sub cube is described as an arbitrary shaped discret and limited sub space of the cube. This illustrated by the following query (Query 1) creating the following sub space (Figure 1 – grey area):

Sub Cube Figure 3
Query 1
Sub Cube Figure 2
Figure 1

One of the important Things to notice about sub cubes are, that the Default member can change, if the “normal” default member is not a part of the sub space. Then the first member of the sub space will become the default member.

I was reconfirmed in most of my knowledge on sub cube when I dug into the documentation on the subject, and nothing would lead me to believe, that the construct was other than a misunderstanding. So I tweetet a question using hashmark #ssashelp, and Brent Ozar (blog|twitter), Chris Webb (blog|twitter) and Robert L Davis (blog|twitter) replied, after twisting some arms 🙂 This lead to this blog post, describing the issue, in just a little more than 140 characters…So lets see what replies are in store! To my best knowledge, the first query in this blog post, is more confusing than brilliant.

SSMS Quick Tip

If you ever need to test Analysis Services roles, you can easily do so either by browsing the cube or by means of a query.

When browsing a cube through SQL Server Management Studio (SSMS) or Bisuness Intelligence Developer Studio (BIDS), you can select one or more roles to be enforced on data, by clicking the little “user” icon in the top left corner of the cube browser:

You will then be able to select on or more of the roles available on the database via a dialog:

This way of browsing roles has the following pros and cons:
Pros: Visual confirmation of PC Hierarchies
Cons: A lot of clicking top verify permission integrity

The other way of testing roles is through SSMS is by creating an MDX query. The trick is to click the options button when the connection dialog is active. The last tab allows you to specify additional connection parameters. The Roles property is described in detail at technet. Basically it’s a comma seperated list of roles (case sensitive). The trick is showed in the screendump below:

Pros: Custom queries
Cons: No visual confirmation of integrity, can be hard to visually confirm permissions on a PC hierarchy as an example

How to get SSAS to return the correct currency format.

Although setting the language and collation correctly, it’s not easy to see why a specific MDX would not return the right formatting, in regards to monetary, thousands seperator etc.
There is however a way of forcing the language, through a property available on the calculated measure. In the following example, I’ll show that even though the server settings are da-DK (Danish), the results are displayed as en-US, unless we provide a property value.

First, a screenshot of the server settings:

Then the query, that returns en-US formatting:

For this to work, we need to add: Language=1030 as property to the calculated member, then we get:

See more on FORMAT_STRING and LANGUAGE @ http://msdn.microsoft.com/en-us/library/cc879322.aspx

MDX Query using other hierarchy in same dimension as in slicer

The other day a coworker of mine presented me with a problem in one of our solutions. His basic pain was, that the front-end of the application only allowed for one dropdown containing whatever dimension was set up to be displayed. This dimension is to act as slicer in a scorecard application. Since his KPIs were aiming different levels of different hierarchies in the date dimension, he was experiencing problems when faced with the choice of only one available date hierarchy.

Luckily we are able to solve this issue by means of MDX.
The following statement should display the solution, by the use of the method EXISTS and the knowledge of the structure of the date dimension hierarchies.

We use the EXISTS function to find the members of the [Date].[Calendar Week] hierarchy with the slicer set to  a member of another hierarchy, in this case [Date].[Calendar].[Date].&[20070201]. Note that we need to get Item(1) of the collection returned, as we get the All member at first index (0).

UPDATE:

As mentioned by Hrvoje Piasevoli (blog|twitter) it is a more clean solution to just query by the tuple made by the week hierarchy and the measure, eg.:

([Date].[Calendar Week].CurrrenMember, [Measures].[Internet Sales Amount])

In our case however, we discovered that the attribute relations in the Date dimension was not setup correctly to allow us to “convert” a member in one hierarchy to another. We ended up with the [All] member of that hierarchy.
We solved the issue by making a common root for the two date hierarchies, as seen in the Adventure Works cube.

Pct af totalen

Et eksempel på hvordan man kan beregne pct. af totalsalg og pct af salget på niveauet over det aktuelle.

WITH

MEMBER [Measures].[Pct of total] AS ‘SUM( {[Product].CurrentMember}, [Measures].[Unit Sales]) /SUM( {[Product].DefaultMember}, [Measures].[Unit Sales])’, FORMAT_STRING=’#0.00%’

MEMBER [Measures].[Pct of parent total] AS ‘IIF( [Product].Parent <> NULL, SUM( {[Product].CurrentMember}, [Measures].[Unit Sales]) /SUM( {[Product].Parent.Children}, [Measures].[Unit Sales]), 1)’, FORMAT_STRING=’#0.00%’

SELECT

{ [Measures].[Unit Sales], [Measures].[Pct of Total], [Measures].[Pct of parent total] } ON COLUMNS,

NON EMPTY Order( DESCENDANTS( [Product]  ),[Measures].[Pct of total], DESC ) ON ROWS

FROM

[Sales]

Et eksempel på totalten af en delmængde:

WITH
SET [Categories] AS {[Product].[Product Categories].[Category].&[4], [Product].[Product Categories].[Category].&[1]}
MEMBER [Measures].[Contribution] AS ([Product].[Product Categories].CurrentMember, [Measures].[Sales Amount]) / SUM([Categories], [Measures].[Sales Amount]), FORMAT_STRING=”#,##0.00%”
SELECT
{ [Measures].[Sales Amount], [Measures].[Contribution] } ON COLUMNS
,{[Categories] } ON ROWS
FROM [Adventure Works]