MDX Time Calculations Done the Right Way

Who is online?  0 guests and 0 members
Home  »  Articles  »  MDX Time Calculations Done the Right Way

MDX Time Calculations Done the Right Way

change text size: A A A
Published: 8/11/2010 by  DevinKnight  - Views:  [2688]  

When creating time calculations in Analysis Services you may take several approaches. For people that have just begin learning SSAS they likely have spent several days writing calculations that return things like year to date, rolling twelve month, and period over period for every measure they have.

For the more adventurous developer they have tried using the Business Intelligence wizard which automates the process of writing time calculations on selected measures. It creates an attribute in the date dimension that can then be used to view calculations. This sounds like a great idea but it is very inflexible when changes are needed and is still specific to the measures that were selected during the wizard configuration. Another problem with the BI wizard is it can only be run against one date dimension hierarchy at a time. With many dimensional models date can mean many different things, it can be a calendar date, fiscal date, ship date, order date, and many others. There is likely only one date table in the data warehouse but plays the role of many different dates making it a role playing dimension. If you wanted those same time calculations for each role playing dimension using the BI wizard you would have to run through the wizard multiple times and then enjoy managing that mess later.

The best way to handle time calculation is detailed in the book Expert Cube Development with Microsoft SQL Server 2008 Analysis Services. You may have heard me sing praises of this book before because the content is that useful for real world problems. What I’m going to show you in this article is my variation of what they show in that book. The benefit of this method is multifold. It is a lot easier to manage than the BI wizard because you have total control of it. It’s dynamic because the formula will work no matter what measure is being viewed. Also, it is easy to filter just the calculations you want because it’s just like any other attribute that you would filter by.  

To follow this example you can download the sample database from www.codeplex.com. When you download and install this sample database you also receive sample files for deploying an Analysis Services cube that can be found here C:\Program Files\Microsoft SQL Server\100\Tools\Samples.

To start this example create a SQL Server view that will simply store the name of the calculation that you want to create and an ID column.

Create VIEW [dbo].[DateCalcs] AS

 SELECT ID = 1, Calculation = 'Actuals'

 UNION ALL

 SELECT ID = 2, Calculation = 'Calendar Year To Date'

 UNION ALL

 SELECT ID = 3, Calculation = 'Fiscal Year To Date'

 UNION ALL

 SELECT ID = 4, Calculation = 'Calendar Previous Period'

 UNION ALL

 SELECT ID = 5, Calculation = 'Fiscal Previous Period'

 UNION ALL

 SELECT ID = 6, Calculation = 'Calendar Previous Period Diff'

 UNION ALL

 SELECT ID = 7, Calculation = 'Fiscal Previous Period Diff'

 

The resulting view looks like this:

 

ID Calculation

1 Actuals

2 Calendar Year To Date

3 Fiscal Year To Date

4 Calendar Previous Period

5 Fiscal Previous Period

6 Calendar Previous Period Diff

7 Fiscal Previous Period Diff

 

Create as many time values for the Calculation column as you will need time calculations in the cube. Here I have created a set of calculations for Calendar and Fiscal because it is likely I will be required to have these calculations for both my Calendar and Fiscal dates.

 

Once this is created add the view to your data source view. Notice after adding the view that it has no relationships to any other object, which is fine because no relationships are needed.

 

Create a new dimension based off the DateCalcs view with the ID column as the Key column and the Calculation column as a regular attribute. Select the ID attribute and change the AttributeHierarchyVisible property to False to hide it from the users. Select the Calculation attribute and change the IsAggregatable property to False. This will remove the All level you are used to seeing in dimensions which isn’t necessary for the dimension.

 

The last step is to select the Calculation attribute and change the DefaultMember property to the Actuals member [Date Calcs].[Calculation].&[Actuals]. When all these changes have been made you can process this dimension. After the processing completes add the new dimension to be used in this cube by going to the Cube Structure tab in the cube designer. To add the dimension right click in the Dimensions pane in the bottom left and select Add Cube Dimension.  Select Date Calcs from the list to make it usable to this cube. You will notice if you view the Dimension Usage tab that it has no relationship to any Measure Group, which is not a problem.

 

 

With the Date Calcs dimension prepped you can now open the Cube designer and open the Calculations tab. Here you will be using the mdx SCOPE statement to handle each of the calculations you wish to use. It does not matter what order we write each of these calculation but the first one we will tackle is Calendar Year To Date. Hit the New Script Command button to get started.

 

Calendar Year To Date

SCOPE ([Date Calcs].[Calculation].[Calendar Year To Date]);

 THIS =

 AGGREGATE (

 YTD ([Order Date].[Calendar Date].CurrentMember),

 [Date Calcs].[Calculation].[Actuals]

 );

END SCOPE

 

Fiscal Year To Date (Using a different method to calculate YTD)

SCOPE ([Date Calcs].[Calculation].[Fiscal Year To Date]);

 THIS =

Aggregate(PeriodsToDate(

[Order Date].[Fiscal Date].[Fiscal Year],

[Order Date].[Fiscal Date].CurrentMember

),

([Date Calcs].[Calculation].[Actuals])

)

;

END SCOPE

Calendar Previous Period

SCOPE ([Date Calcs].[Calculation].[Calendar Previous Period]);

THIS =

([Order Date].[Calendar Date].CurrentMember.PrevMember,

[Date Calcs].[Calculation].[Actuals]);

END SCOPE

Fiscal Previous Period

SCOPE ([Date Calcs].[Calculation].[Fiscal Previous Period]);

THIS =

([Order Date].[Fiscal Date].CurrentMember.PrevMember,

[Date Calcs].[Calculation].[Actuals]);

END SCOPE

Calendar Previous Period Diff

SCOPE ([Date Calcs].[Calculation].[Calendar Previous Period Diff]);

THIS =

([Order Date].[Calendar Date].CurrentMember,

[Date Calcs].[Calculation].[Actuals])-

([Order Date].[Calendar Date].CurrentMember.PrevMember,

[Date Calcs].[Calculation].[Actuals]);

END SCOPE

Fiscal Previous Period Diff

SCOPE ([Date Calcs].[Calculation].[Fiscal Previous Period Diff]);

THIS =

([Order Date].[Fiscal Date].CurrentMember,

[Date Calcs].[Calculation].[Actuals])-

([Order Date].[Fiscal Date].CurrentMember.PrevMember,

[Date Calcs].[Calculation].[Actuals]);

END SCOPE

This gives you a good start on a Time Calculation dimension. Once these calculations are written you will need to process the cube. You may have noticed that in each of these calculations I never actually identify a measure that exists in the cube. That is actually the beautiful thing about this technique is that it works across all measures now! So instead of having to create a calculation for Sales, Profit, and all the other measures in the cube you only have to create this calculation once and it will work on all measures. Try it out yourself!

 
0
/5
Avg: 0/5: (0 votes)

Comments (22)

PatrickLeBlanc

This will be useful

8/11/2010
 · 
 
by
Frankkearney
Frankkearney said:

I love this approach to time calculations and the idea of the "hanger" dimension. ?

My only question would be how would this be used if I were creating a SSRS report where on the rows were say Regions and the first column was Net Dollars and the next column was Gross dollars all Week to Date?

8/12/2010
 · 
 
by
Daniel
Daniel said:

This is a really fascinating approach.  I never really thought of doing dimension table calculations before.  This could be a real time saver.  Great article, thanks.

8/18/2010
 · 
 
by
MarkGStacey
MarkGStacey said:

Interesting approach Devin, nice

 

 

I typically use a variation, where I have *three* columns, and store the calculation in the table ~ there are several other differences that are required when doing this, which may well make this an easier implementation.

 

 

Thanks for the info!

8/23/2010
 · 
 
by
nashworth
nashworth said:

This is great stuff, I have applied a similar solution (based on a Marco Russo Article here http://sqlblog.com/blogs/marco_russo/archive/2007/09/02/datetool-dimension-an-alternative-time-intelligence-implementation.aspx) this allows you to view comparisons across various aggregations such as Ytd, Period to Date, Rolling 13/26/52 Weeks etc 

9/1/2010
 · 
 
by
nashworth
nashworth said:

This is great stuff, I have applied a similar solution (based on a Marco Russo Article here http://sqlblog.com/blogs/marco_russo/archive/2007/09/02/datetool-dimension-an-alternative-time-intelligence-implementation.aspx) this allows you to view comparisons across various aggregations such as Ytd, Period to Date, Rolling 13/26/52 Weeks etc 

9/1/2010
 · 
 
by
DevinKnight
DevinKnight said:

Yep!  Marco is actually one of the coauthors of the book I recommend in the beginning of the article.

9/8/2010
 · 
 
by
AndrewWiles
AndrewWiles said:

Referring to Mark's comment. If you have only one cube that uses these calculations then it is easier to maintain them in the script. If you have multiple cubes that share the calculations then you would be better adding the column to the table and using the custom rollup options.

9/10/2010
 · 
 
by
charliebruno
charliebruno said:

I have read a few variations of this technique recently, and being a novice with SSAS/MDX, I do not understand how or where the reference to the measure group fields are, or how this is accomplished. I am "getting" the intent here, however, I do not see where the references to the individual measures are made. I would think that this new dimension would have some sort of REFERENCED relationship to the measure group through the date(time) dimension.

Second question: the first two calculations, Calendar YTD and Fiscal YTD, I would think these two calcs would be identical with the exception of the time heirarch used(Cal vs Fiscal). One calc uses the YTD function, the other PERIODSTODATE. Why the difference?

9/29/2010
 · 
 
by
DevinKnight
DevinKnight said:

Great questions.  The Scope statement handles the relationships and if I remember right I think I just did it two different ways to show they can do the same thing.

9/30/2010
 · 
 
by
charliebruno
charliebruno said:

Shortly after I posted the question, I noticed the parenthetical comment that explained the different method of determining YTD.

I still do not see the referencing to the fact table measures. I apologize if I sound obtuse, and asking this question again, but I do not see where or how the fact table measures are tying into this solution.

You have noted above: You will notice if you view the Dimension Usage tab that it has no relationship to any Measure Group, which is not a problem.

Additional note: I recently purchased your video "Knight's Summer School BI". An excellent instructional work. You guys are a riot. Very educational, entertaining, and fun to view.

9/30/2010
 · 
 
by
DevinKnight
DevinKnight said:

No problem.  I guess my wording in the previous comment is confusing.  It actually doesn't require a relationship.  You can almost think of the scope statement as if it's just doing a regular calculation, but it's saying when you drag this member into the query[Date Calcs].[Calculation].[Fiscal Year To Date])then preform the following calculation.

Glad you liked the DVD!  For anyone else interested...

https://www.vconferenceonline.com/shows/summer10/pragmatic/register/Indexingdvd_pragmatic.asp?newmem=1&show=&utm_source=streamsend&utm_medium=email&utm_content=12632627&utm_campaign=DVD%3A%20Knight%27s%20Business%20Intelligence%20Summer%20School

9/30/2010
 · 
 
by
aganatraDNB
aganatraDNB said:

Great approach and it works well. When users access the data via Excel, for Periods To Date column, they see data for future Fiscal Weeks as well. Is there a way to hide/supress the data in rows for Fiscal Period To Date column when there is no data in Fiscal Week column?

Same thing happens for Fiscal Year To Date As well.

Thank you,

Amit

12/1/2010
 · 
 
by
DevinKnight
DevinKnight said:

Good question.  I'll see if I can find a way.

12/2/2010
 · 
 
by
aganatraDNB
aganatraDNB said:

One more question on the same topic. The calculation gives me the value of prev member. Is there a way you can tell me how to get data for same member from prior year. i.e. when I am looking at Prev Period for Q4 of FY 2010 I want to see Q4 2009  or when looking at Prd 3 2010 I want to see Prd3 2009. I have listed the calculation from your article.

Fiscal Previous Period

SCOPE ([Date Calcs].[Calculation].[Fiscal Previous Period]);

THIS =

([Order Date].[Fiscal Date].CurrentMember.PrevMember,

[Date Calcs].[Calculation].[Actuals]);

END SCOPE

12/2/2010
 · 
 
by
bgeiger
bgeiger said:

http://fsugeiger.blogspot.com/2010/03/test_26.html

1/11/2011
 · 
 
by
jmbaute
jmbaute said:
I'm struggling with getting the dimension to order properly...since I'm using it in a PerformancePoint scorecard, the scorecard uses the dimension order when placing columns left to right. The calculation attribute sorts alphabetically, not by the ID column. Any ideas? I've tried various things that all seem to blow up the dimension.
28 days ago
 · 
 
by
jmbaute
jmbaute said:
A question on a blog or forum always leads me to answer my own post. Here's what I did: - added a computed column called Order in the DSV which is just the ID field - made this an attribute of the Calculation field in the dimension, created a relationship Calculation-> Order - set Calculation's OrderBy property to AttributeKey - selected the OrderBy column as the OrderByAttribute Probably obvious to a lot of folks but this might help other noobs out there.
28 days ago
 · 
 
by
user809288
user809288 said:
This is really neat! Is there a way to change the format of the field using this method? I want to display a [Previous Period Diff %] calculation, which I've implemented like this: //Previous Period Diff % SCOPE ([Date Calcs].[Calculation].[Previous Period Diff %]) THIS = (([Calendar - Sales].[Monthly Calendar].CurrentMember, [Date Calcs].[Calculation].[Actuals])- ([Calendar - Sales].[Monthly Calendar].CurrentMember.PrevMember, [Date Calcs].[Calculation].[Actuals])) / ([Calendar - Sales].[Monthly Calendar].CurrentMember.PrevMember, [Date Calcs].[Calculation].[Actuals]) END SCOPE When I pull in the other calculations and apply them to [Revenue USD], the output is correctly formatted as USD. However, when I pull in this [Previous Period Diff %], it displays as a number, like 0.35, rather than a percent, like 35%. If I then format it inside Excel, it changes the format for ALL the [Revenue USD] calculations to %. How can I change the formatting on the SSAS side so that it comes across appropriately to Excel?
5 days ago
 · 
 
by
user809288
user809288 said:
Whoa, sorry about the formatting there. My line breaks got removed somehow.
5 days ago
 · 
 
by
DevinKnight
DevinKnight said:
Sure can. Here's a post that shows how. http://bidn.com/blogs/schilders/ssas/971/number-formatting-in-mdx-scope-statement Well looks like actually the code is in the comments.
5 days ago
 · 
 
by
user809288
user809288 said:
Excellent. Thanks!
4 days ago
 · 
 
by

Most Recent Articles