Ok, so for my first post I figured I would write about something that just happened the other day that I thought was pretty cool. By the way, this is pretty much going to be the format of this blog, when I do something that I think is cool, I'll write about it and if anyone can get any benefit out of it cool. So as I was saying, I came up against a little challenge the other day and the result came out pretty nicely. At the end of the day I had to create two different time roll-ups in my ASO cube. I thought about actually doing two different time dimensions (what the hell it's an ASO cube I can have as many dimensions as I want) I resisted this temptation and went back to my OLAP basics, would the two dimensions have any meaning if I cross tabbed them in a report? Answer: no; so I went back to alternate roll-up.
Now an Alternate roll-up is certainly nothing new, and probably not worth writing about in and of itself, but this one did pose a couple of challenges. (For those of you who are new, alternate roll-ups are pretty much what they sound like, an alternate way of rolling certain members up in a hierarchy. For example you might have a member called [New York] that rolls up to a member called [North East Region]. You could then share the member [New York] and roll it up under another member like [Major Markets]).
So first let me set the stage. For starters, this database goes down to the daily level. The data set in this application flows on what is called a Production calendar. Basically the Production calendar runs a few days short on each month, so the month of June ends on June 23th and the month of July begins on June 24th. Now we had already hashed this out with the users and had them provide the production calendar for the next two years so I could integrate it with my standard calendar. Now is a good time to mention that I've built my own little master data repository where I store approx 4 - 5 standard hierarchies that I use throughout multiple applications. I have a standard time dim (which also has built in the company's fiscal calendar) then I have a structure for the GL, a Cost Center roll-up, and another one for a Branch hierarchy. For most of these structures I have both Parent/Child and Gen/Level tables so I have a lot of flexibility in using with EIS or SQL load rules. Whenever I build a new app chances are one of these structures will be used so I just go grab them from the central repository. Perhaps I can post another time and get more in depth about what I am doing there. Getting back to this post, I pull down the time structure and I join it with the Prod calendar the users provided me and we built the Production calendar for the app. After a while the users kept coming up with issues they were having, it seems all internal reporting is on Production calendar but anything going external, especially reporting that needed to match up against other third parties was all done on regular calendar (i.e. June is 6/1-6/30). I gave it some thought and came up with a pretty quick way to do it. I already had the regular time roll-up and my time dim in EIS was pointing to a view so I could simply modify my view with a UNION query to bring in the regular time roll-up. I had to do some manipulation to keep the upper level members unique. All I had to do was prefix all Prod calendar members with 'PY' (i.e. [PY2008-Q1]) and then Fiscal year with 'FY' (i.e. [FY2008-Q1]).
The SQL query looked like this
SELECT 'Production Calendar' AS Hierarchy, 'PY' + CAST(prod_yr AS varchar) AS fiscal_year, 'PY' + CAST(prod_yr AS varchar) + '-Q' + CAST(prod_qtr_no AS varchar) AS fiscal_qtr, 'Q' + CAST(prod_qtr_no AS varchar) + '-' + 'PY' + CAST(prod_yr AS varchar) AS fiscal_qtr_desc, 'PY' + CAST(prod_yr AS varchar) + '-' + RIGHT('00' + CAST(prod_mo_no AS varchar), 2) AS month, prod_mo_short + '-' + 'PY' + CAST(prod_yr AS varchar) AS month_desc, CAST(cal_year AS varchar) + '-' + RIGHT('00' + CAST(cal_mo_no AS varchar), 2) + '-' + RIGHT('00' + CAST(cal_day_no AS varchar), 2) AS day, prod_mo_short AS month_attr, prod_mo_sort AS month_attr_sort, cal_day_short AS day_attr, cal_day_of_week_no AS day_attr_sort, weekday, sort_id, NULL AS alias
FROM dbo.Periods
WHERE (US_TRADE_DATE <> 0) AND (prod_yr IS NOT NULL)
UNION
SELECT TOP 100 PERCENT 'Fiscal Calendar' AS Hiearchy, 'FY' + CAST(fiscal_year AS varchar) AS fiscal_year, 'FY' + CAST(fiscal_year AS varchar) + '-Q' + CAST(fiscal_qtr_no AS varchar) AS fiscal_qtr, 'Q' + CAST(fiscal_qtr_no AS varchar) + '-' + 'FY' + CAST(fiscal_year AS varchar) AS fiscal_qtr_desc, 'FY' + CAST(cal_year AS varchar) + '-' + RIGHT('00' + CAST(cal_mo_no AS varchar), 2) AS month, cal_month_short + '-' + 'FY' + CAST(cal_year AS varchar) AS month_desc, CAST(cal_year AS varchar) + '-' + RIGHT('00' + CAST(cal_mo_no AS varchar), 2) + '-' + RIGHT('00' + CAST(cal_day_no AS varchar), 2) AS day, cal_month_short AS month_attr, prod_mo_sort AS month_attr_sort, cal_day_short AS day_attr, cal_day_of_week_no AS day_attr_sort, weekday, 1000000 + sort_id AS sort_id, NULL AS alias
FROM dbo.Periods AS Periods_1
WHERE (US_TRADE_DATE <> 0) AND (prod_yr IS NOT NULL) ORDER BY sort_id
The result set looked like this
The next step was to modify my EIS meta-outline to allow for multiple hierarchies. So I went to the properties for the dim and went to the Outline Build properties. I set it to 'Stored for All Alternate Hierarchies'. This setting tells Essbase when building this dimension to make the root member allow multiple hierarchies and set all Gen 2 members to Stored. This was ideal for this app, I didn't want to loose any performance with the alternate roll-up so by having both hierarchies stored I'm able to maximize performance on both hierarchies.
The end result worked out really well
Here's what the Prod Year looked like
And here's what the Fiscal year looked like
Once I had the Time roll-ups in place I loaded the data and ran an aggregation. I cranked it up to about 10x the initial data load size and it flies! Query response is very fast.
End users can now see data both ways.
This was a quick win, total development time was less than two hours.
Feel free to post comments.
Now an Alternate roll-up is certainly nothing new, and probably not worth writing about in and of itself, but this one did pose a couple of challenges. (For those of you who are new, alternate roll-ups are pretty much what they sound like, an alternate way of rolling certain members up in a hierarchy. For example you might have a member called [New York] that rolls up to a member called [North East Region]. You could then share the member [New York] and roll it up under another member like [Major Markets]).
So first let me set the stage. For starters, this database goes down to the daily level. The data set in this application flows on what is called a Production calendar. Basically the Production calendar runs a few days short on each month, so the month of June ends on June 23th and the month of July begins on June 24th. Now we had already hashed this out with the users and had them provide the production calendar for the next two years so I could integrate it with my standard calendar. Now is a good time to mention that I've built my own little master data repository where I store approx 4 - 5 standard hierarchies that I use throughout multiple applications. I have a standard time dim (which also has built in the company's fiscal calendar) then I have a structure for the GL, a Cost Center roll-up, and another one for a Branch hierarchy. For most of these structures I have both Parent/Child and Gen/Level tables so I have a lot of flexibility in using with EIS or SQL load rules. Whenever I build a new app chances are one of these structures will be used so I just go grab them from the central repository. Perhaps I can post another time and get more in depth about what I am doing there. Getting back to this post, I pull down the time structure and I join it with the Prod calendar the users provided me and we built the Production calendar for the app. After a while the users kept coming up with issues they were having, it seems all internal reporting is on Production calendar but anything going external, especially reporting that needed to match up against other third parties was all done on regular calendar (i.e. June is 6/1-6/30). I gave it some thought and came up with a pretty quick way to do it. I already had the regular time roll-up and my time dim in EIS was pointing to a view so I could simply modify my view with a UNION query to bring in the regular time roll-up. I had to do some manipulation to keep the upper level members unique. All I had to do was prefix all Prod calendar members with 'PY' (i.e. [PY2008-Q1]) and then Fiscal year with 'FY' (i.e. [FY2008-Q1]).
The SQL query looked like this
SELECT 'Production Calendar' AS Hierarchy, 'PY' + CAST(prod_yr AS varchar) AS fiscal_year, 'PY' + CAST(prod_yr AS varchar) + '-Q' + CAST(prod_qtr_no AS varchar) AS fiscal_qtr, 'Q' + CAST(prod_qtr_no AS varchar) + '-' + 'PY' + CAST(prod_yr AS varchar) AS fiscal_qtr_desc, 'PY' + CAST(prod_yr AS varchar) + '-' + RIGHT('00' + CAST(prod_mo_no AS varchar), 2) AS month, prod_mo_short + '-' + 'PY' + CAST(prod_yr AS varchar) AS month_desc, CAST(cal_year AS varchar) + '-' + RIGHT('00' + CAST(cal_mo_no AS varchar), 2) + '-' + RIGHT('00' + CAST(cal_day_no AS varchar), 2) AS day, prod_mo_short AS month_attr, prod_mo_sort AS month_attr_sort, cal_day_short AS day_attr, cal_day_of_week_no AS day_attr_sort, weekday, sort_id, NULL AS alias
FROM dbo.Periods
WHERE (US_TRADE_DATE <> 0) AND (prod_yr IS NOT NULL)
UNION
SELECT TOP 100 PERCENT 'Fiscal Calendar' AS Hiearchy, 'FY' + CAST(fiscal_year AS varchar) AS fiscal_year, 'FY' + CAST(fiscal_year AS varchar) + '-Q' + CAST(fiscal_qtr_no AS varchar) AS fiscal_qtr, 'Q' + CAST(fiscal_qtr_no AS varchar) + '-' + 'FY' + CAST(fiscal_year AS varchar) AS fiscal_qtr_desc, 'FY' + CAST(cal_year AS varchar) + '-' + RIGHT('00' + CAST(cal_mo_no AS varchar), 2) AS month, cal_month_short + '-' + 'FY' + CAST(cal_year AS varchar) AS month_desc, CAST(cal_year AS varchar) + '-' + RIGHT('00' + CAST(cal_mo_no AS varchar), 2) + '-' + RIGHT('00' + CAST(cal_day_no AS varchar), 2) AS day, cal_month_short AS month_attr, prod_mo_sort AS month_attr_sort, cal_day_short AS day_attr, cal_day_of_week_no AS day_attr_sort, weekday, 1000000 + sort_id AS sort_id, NULL AS alias
FROM dbo.Periods AS Periods_1
WHERE (US_TRADE_DATE <> 0) AND (prod_yr IS NOT NULL) ORDER BY sort_id
The result set looked like this
Fiscal Calendar | FY2008 | FY2008-Q3 | Q3-FY2008 | FY2008-06 | Jun-FY2008 | 2008-06-30 | Jun | 8 | Mon | 2 | Y | 1039627 | NULL | |
Production Calendar | PY2008 | PY2008-Q3 | Q3-PY2008 | PY2008-07 | Jul-PY2008 | 2008-06-30 | Jul | 8 | Mon | 2 | Y | 39627 | NULL |
The next step was to modify my EIS meta-outline to allow for multiple hierarchies. So I went to the properties for the dim and went to the Outline Build properties. I set it to 'Stored for All Alternate Hierarchies'. This setting tells Essbase when building this dimension to make the root member allow multiple hierarchies and set all Gen 2 members to Stored. This was ideal for this app, I didn't want to loose any performance with the alternate roll-up so by having both hierarchies stored I'm able to maximize performance on both hierarchies.
The end result worked out really well
Here's what the Prod Year looked like
And here's what the Fiscal year looked like
Once I had the Time roll-ups in place I loaded the data and ran an aggregation. I cranked it up to about 10x the initial data load size and it flies! Query response is very fast.
End users can now see data both ways.
This was a quick win, total development time was less than two hours.
Feel free to post comments.
Comments
Did you have the requirement for MTD, YTD calculations etc... with the alternate time hierarchies?
If so, how did you deal with the YTD value on the shared members where the total would be different to the of the YTD value for the stored member?
Thanks
M
Thanks for getting back to me. I have a view dimension with WTD, MTD, QTD and YTD defined. Both hierarchies go to a daily level with the days shared members in the alternate hierarchy.
Is it possible to have an alternate YTD rollup on the days in this shared hierarchy?
I am thinking I either have to store the second calendar or make it dynamic. However making dynamic causes issues with the MDX to get the TB_Last value on the alternate as you cant use functions such as LEAVES.
Thanks
M