Archive

Posts Tagged ‘MDX’

Creating a set that excludes certain members from a hierarchy using MDX exclude and descendant

October 1st, 2009 Kasper de Jonge No comments

I have a report where the client wants to exclude all but 3 members below a certain level from a hierarchy.

The easiest way to achieve this is to exclude them when designing the query in BIDS, but this is much work and not easy to maintain, especially when you want to use this in multiple reports. And when this hierarchy is changed it will automatically be included even when we don’t want it.

I thendecided to create a set that includes all the members that need to be excluded, so i can use a NOT IN while designing the query. After browsing the internet i found How to exclude a certain member from a MDX call that gets all descendants of a member at a higher level. Exactly what i needed. It works like this:

Select all the members from the level i need from the hierarchy by using DESCENDANTS :

DESCENDANTS([Product].[Product Categories].[Category].&[4],
[Product].[Product Categories].[Product],
SELF)

This will select all the Products from the Category “Accessories”,

Next we want to Exclude the Products we still want in our set, we do this by using the Except function, this function lets you distract the values from one set from another:

Except(
DESCENDANTS([Product].[Product Categories].[Category].&[4],
[Product].[Product Categories].[Product],
SELF)
,  { [Product].[Product Categories].[Product].&[483]
,[Product].[Product Categories].[Product].&[486]
}
)

The { } around the products make it a set so they can be distracted using Except. This statement can be added as a Set to the Cube, and thus used in the Query to build the dataset by using NOT IN and selecting the SET.

To test this I made the following MDX statement to execute at the Query analyzer:

SELECT
{} ON COLUMNS,
{
Except(
DESCENDANTS([Product].[Product Categories].[Category].&[4],
[Product].[Product Categories].[Product],
SELF)
,{[Product].[Product Categories].[Product].&[483]
,[Product].[Product Categories].[Product].&[486]})
}
ON ROWS
from [Adventure Works]

Categories: Analysis services, MDX Tags: ,

MDX Working with default time function in named sets

April 29th, 2009 Kasper de Jonge No comments

I have a cube to which report builders connect to make reports with report builder 2.0, since they don’t want to write MDX for complex functions and just use drag and drop to create the reports i decided to create named sets with some default time functions like YTD,  YTD previous year, year difference, current month, previous month and moth difference. This blog post tells the story of that achievement  :) .

To start with i have a pretty simple time dimension time with a simple hierarchy:

image

 

As first step i tried the most simple: current month. My initial thought was to use the LASTCHILD function with the following expression:
[Time].[Month].LASTCHILD
this looked ok, but on closer inspection it seems to return the last Month level, so when your in april (month 4) of 2009 but you have december (12) in your dimension as well it would return 12. After some googling i came up with a new idea, to create a new attribute called yearmonth (combine the 2 in the DSV) and use the LASTCHILD of that field, that worked but i didn’t feel good with me, I left it a while and continued with the rest and found the function ClosingPeriod some time later, this function returns the last member of a time level, perfect :) . I rewrote the function accordingly:
ClosingPeriod([Time].[Calendar].[Month])
Watch me use the complete hierarchy expression here, one thing that helped me alot understanding all these expression was the debug function of Mosha’s MDX Studio. 

Next up was previous month, the obvious function was to use ParallelPeriod, which eventually formed:
ParallelPeriod ([Time].[Calendar].[Month],1,ClosingPeriod([Time].[Calendar].[Month])).
Which worked great.

now to join these 2 (and use them on the x-axis on a report) i found the function Union:
Union ([Current Month] ,[Previous month])
I tried using crossjoin but the sets use the same dimension and thats not usable in crossjoin)

Now for the year level, Current year to date:
Ah this one is easy using the YTD function, first i used YTD([Time].[year].LASTCHILD) this returned the year in the set but i decided to use the ClosingPeriod again which returns the months of the current year in the set:
YTD(ClosingPeriod([Time].[Calendar].[Month]))

The last on my todo list is YTD from the previous year, this one took the longest to finish and let me to eventually find the ClosingPeriod function which made my life a lot easier :)

YTD(ParallelPeriod([Time].[Calendar].[Year]
, 1
, ClosingPeriod([Time].[Calendar].[Month]))
Get the current month and go back one year from that, determine the year to date to that month.

Join these tow named sets together to get a year difference, to do that i needed 2 identical sets with the same level, in my first YTD statement i used [Time].[year].LASTCHILD) this function uses the year level while the ytd from previous year uses the month level, these two aren’t joinable. This is the reason i used the ClosingPeriod on the YTD, it now returns a month and will lead the ytd function to return the months of the year.
So now i could use UNION:
Union ([Current year to date],[Previous year to date])

Eventually leading to the following script:

image

SQL Server 2008 White Paper: Analysis Services Performance Guide

February 19th, 2009 Kasper de Jonge No comments

Microsoft has  published a white paper describes how application developers can apply query and processing performance-tuning techniques to their SQL Server 2008 Analysis Services OLAP solutions

Because Microsoft SQL Server Analysis Services query and processing performance tuning is a fairly broad subject, this white paper organizes performance tuning techniques into the following three segments.

Enhancing Query Performance – Query performance directly impacts the quality of the end user experience. As such, it is the primary benchmark used to evaluate the success of an online analytical processing (OLAP) implementation. Analysis Services provides a variety of mechanisms to accelerate query performance, including aggregations, caching, and indexed data retrieval. In addition, you can improve query performance by optimizing the design of your dimension attributes, cubes, and Multidimensional Expressions (MDX) queries.

Enhancing Processing Performance – Processing is the operation that refreshes data in an Analysis Services database. The faster the processing performance, the sooner users can access refreshed data. Analysis Services provides a variety of mechanisms that you can use to influence processing performance, including efficient dimension design, effective aggregations, partitions, and an economical processing strategy (for example, incremental vs. full refresh vs. proactive caching).

Tuning Server Resources – There are several engine settings that can be tuned that affect both querying and processing performance.

Read the entire report at: Sqlcat

The Baker's Dozen: 13 Tips for Querying OLAP Databases with MDX

February 19th, 2009 Kasper de Jonge No comments

MDX is just like Transact-SQL, right? MDX is English-like and therefore easy to learn, right? Different software tools offer MDX generators and therefore I don’t need to learn MDX, right? MDX isn’t that popular, right?

Well, just like the punch line of the old Hertz car rental commercial, “Not exactly.” If your organization uses OLAP databases, you can add great value by knowing how to query OLAP databases using MDX queries. MDX is to OLAP databases as SQL queries are to relational databases. This article will cover common OLAP query requirements and MDX code solutions.

Bill Baker has created an article for MDX starter, a great startup. Read the whole article here:  DevX Article

Categories: BI Technical Tags: ,