Monthly Archives: April 2014

Rank Functions in MDX

I know its looks weird to ask for Rank function”s” in MDX because there is only one for it.
But in SQL we have multiple Rank functions and used under different circumstances for solving different purposes. Those are RANK, ROW_NUMBER, NTILE and DENSE_RANK.

If SQL has it why not in MDX!!!! So I tried to give you few examples so that you can call the functionality of Rank functions of SQL in MDX. I saw few post online but those were so bloody complex that it took time for me to understand what they were trying to do, and yet not much useful.

Below is the Query with different calculated measures and then the screenshot from the result. Calculated measure names are actually based on T+SQL ranking functionality:


WITH

MEMBER [MEASURES].[SEM_COUNT] AS
COUNT(NONEMPTY([Date].[Calendar].[Calendar Semester].MEMBERS
,[Measures].[Order Count]) )
--This measure gives me repeating values and I needed same in
--showing example Rank

MEMBER [ROW_NUMBER] AS
RANK(([Product].[Category].CURRENTMEMBER
,[Product].[Subcategory].CURRENTMEMBER) ,
[Product].[Category].[Category]
*[Product].[Subcategory].[Subcategory]
)
-- Identity column for all the rows in result set

MEMBER [ROW_NUMBER_ORDER] AS
RANK([Product].[Category].CURRENTMEMBER,
ORDER([Product].[Category].[Category],[Measures].[Order Count], ASC))
-- To Replace ORDER BY of ROW_NUMBER in SQL by using MDX ORDER
-- it works same as expected, ranking of rows are done based on measure

MEMBER [ROW_NUMBER_PARITION] AS
RANK(([Product].[Category].CURRENTMEMBER,
[Product].[Subcategory].CURRENTMEMBER) ,
[Product].[Category].CURRENTMEMBER
*[Product].[Subcategory].[Subcategory]
)
-- To have a functionality of PARTITION BY in SQL, i built this example
-- where Ranks/ Row Numbers are given based on Category and Subcategory
-- it is not same as identity column as given above

MEMBER [RANK_DENSE] AS
RANK([Product].[Category].CURRENTMEMBER,
[Product].[Category].[Category]
)
-- It’s actually Dense Rank of SQL that we have RANK in MDX
-- Here we don’t do any manipulation and look we have a Dense rank for
-- for Categories
-- Important to Note is that Categories ranks are coming like 1,1,1,1 then 2,2,2,2
-- Not like 1,1,1,1 and 5,5,5,5

MEMBER [RANK] AS
RANK(([Product].[Category].CURRENTMEMBER,
[Product].[Subcategory].CURRENTMEMBER) ,
[Product].[Category].CURRENTMEMBER
*[Product].[Subcategory].[Subcategory]
, [MEASURES].[SEM_COUNT]
)
-- This is example for RANK in SQL
-- Important to Note is that if the measure value
-- are same for multiple rows then values will be like 1,1,1 then 4,4,6 . . .
-- which is expected from RANK function on SQL but here it is a bit complex
-- To get this we have to use Current Member and Measure in Rank properly

SELECT {[ROW_NUMBER],
[ROW_NUMBER_PARITION],
[ROW_NUMBER_ORDER],
[RANK_DENSE],
[RANK],
[MEASURES].[SEM_COUNT],
[Measures].[Order Count]} ON 0,

-- ORDER function below doesn’t impact anything for RANK measures.
ORDER ({[Product].[Category].[Category]}
* {[Product].[Subcategory].[Subcategory]}
, [Measures].[Order Count])

ON 1
FROM [Adventure Works]
-- Below filter I used to validate few points in Ranks of result set. You can
-- of course avoid.
WHERE [Date].[Calendar].[Calendar Semester].&[2008]&[2]

Result (click on image to enlarge)
Result: Rank Funcitons in MDX

So you can study the MDX and result from the post. Here I can explain in detail what I did in MDX for different cases but I believe these example are simplest I can come up with and can be understood easily. Still in case of any doubt or explanation needed please comment and I’ll be ready to help.

These example doesn’t have NTILE but I’ll try to get some time and add alternative for it later.