how to determine which date hierarchy a user is drilling through - ssas

I am trying to implement a calculation dimension along the lines of the DateTool mechanism as outlined in the Expert Cube Development book by Chris Webb et al.
The issue is that, like most organizations, we have the need to report by both fiscal and calendar hierarchies, and based on multiple dates in our transaction table.
I would dearly love to be able to define one calculation dimension which redefines which time dimension and which calendar it uses based on which time dimension and hierarchy the user has chosen.
Here is a sample bit of code:
( [Time Calculations].[Calculation].[Year to Date] )
=
Sum(PeriodsToDate([Time Order Date].[Fiscal Date].[Fiscal Year Name],
[Time Order Date].[Fiscal Date].CurrentMember
),
[Time Calculations].DefaultMember
)
I would very much like to rewrite this as:
( [Time Calculations].[Calculation].[Year to Date] )
=
case
when user is viewing using the Order Date, Fiscal Calendar then
Sum(PeriodsToDate([Time Order Date].[Fiscal Date].[Fiscal Year Name],
[Time Order Date].[Fiscal Date].CurrentMember
),
[Time Calculations].DefaultMember
)
when user is viewing using the Ship Date, Fiscal Calendar then
Sum(PeriodsToDate([Time Ship Date].[Fiscal Date].[Fiscal Year Name],
[Time Ship Date].[Fiscal Date].CurrentMember
),
[Time Calculations].DefaultMember
)
when user is viewing using the Order Date, Calendar hierarchy then
Sum(PeriodsToDate([Time Order Date].[Calendar].[Year Name],
[Time Order Date].[Date].CurrentMember
),
[Time Calculations].DefaultMember
)
when user is viewing using the Ship Date, Calendar hierarchy then
Sum(PeriodsToDate([Time Ship Date].[Date].[Year Name],
[Time Ship Date].[Date].CurrentMember
),
[Time Calculations].DefaultMember
)
else null end
Is this possible?

You could try to insert following into your cube script. This should be aware of any Year levels no matter whether they are used on an axis or in a subselect.
This code uses the fact that dynamic sets are aware of subselects. In addition to that the keyword Existing is used in the IIF so that the calculation also knows about the hierarchies used in the WHERE clause or an Axis.
The Head function is there for performance reasons. You just need to know if at least 1 member of the dimensions is selected. There is no need to count all of them.
The script returns NULL when none of the required hierarchies are selected.
CREATE HIDDEN DYNAMIC SET CURRENTCUBE.[OrderDateFiscalYearAll]
AS [Time Order Date].[Fiscal Date].[Fiscal Year Name].MEMBERS;
CREATE HIDDEN DYNAMIC SET CURRENTCUBE.[OrderDateCalendarYearAll]
AS [Time Order Date].[Calendar].[Year Name].MEMBERS;
CREATE HIDDEN DYNAMIC SET CURRENTCUBE.[ShipDateFiscalYearAll]
AS [Time Ship Date].[Fiscal Date].[Fiscal Year Name].MEMBERS;
CREATE HIDDEN DYNAMIC SET CURRENTCUBE.[ShipDateCalendarYearAll]
AS [Time Ship Date].[Calendar].[Year Name].MEMBERS;
Scope([Time Calculations].[Calculation].[Year to Date]);
This = IIF(Count(Head(Existing [OrderDateFiscalYearAll], 1)) > 0
,/* Insert OrderDateFiscalYear calculation here */
,IIF(Count(Head(Existing [OrderDateCalendarYearAll], 1)) > 0
,/* Insert OrderDateCalendarYear calculation here */
,IIF(Count(Head(Existing [ShipDateFiscalYearAll], 1)) > 0
,/* Insert ShipDateFiscalYear calculation here */
,IIF(Count(Head(Existing [ShipDateCalendarYearAll], 1)) > 0
,/* Insert ShipDateCalendarYear calculation here */
,NULL))))
End Scope;

Related

MDX Calculation for summing the product of two measures and multiplying that by the last children of two other metrics

Here is a snip of my cube's dimension usage:
In "TD Measures" I have
[A] "Billable Client Hours Current".
In "Personnel Measures" I have
[B] "FTE Count" (an employee's amount they are working like .5 for
people who work 20 hours per week)
[C] "Forecast FY End" Forecast for the end of the fiscal year
[D] "Forecast FYTD" Forecast for the current period to date in the fiscal year.
The calculation I need to do at a leaf level is:
[A][B][C]/[D]
The issue is that [A] has more dimensionality that [B], [C], and [D].
So If this is my data:
The calc I need to do is:
((15*.05)+(5*1)) //sum of hours in a period multiplied by that month's FTE
X 2000/300 //last child of FCFYE divided by last child of FCFYTD in the currently selected set.
This calc is likely to change a little over the next week or two, but this is the main concept of what they are looking to do. Any help in writing the MDX for this to create a calculated member in my cube is greatly appreciated. Sorry if I've left out any key info--I'm quite the MDX noob.
Through digging through Chris Webb's and Mosha's posts as well as working with some guys on the MSDN forums I have worked out a solution to this below. Ultimately, I worked out with the business that we didn't need to interrogate the underlying rows to discern if they were active or not since the addition of the root functionality eliminated the need as long as they filtered on it from DimMiscellaneous. But for the sake of helping someone with a similar problem here is the full MDX below.
//Only evaluate if they are active
CREATE HIDDEN UtilizedFTESummator;
[Measures].[UtilizedFTESummator] = Iif([Measures].[Is Active For Utilization Value] > 0,[Measures].[Period FTE],NULL);
NON_EMPTY_BEHAVIOR([Measures].[UtilizedFTESummator]) = [Measures].[Is Active For Utilization Value];
//only include this measure if the underlying employee has values in their underlying data for active in utilization
CREATE MEMBER CURRENTCUBE.[Measures].[FTE Active Utilization]
AS
SUM
(
EXISTING [Historical Personnel].[Employee Id].[Employee Id],
[Measures].[UtilizedFTESummator]
),VISIBLE=0;
//Show weighted FTE by workdays
CREATE MEMBER CURRENTCUBE.[Measures].[FTE MTD Active Utilization]
AS SUM
(
DESCENDANTS([Historical Personnel].[Employee Id].CURRENTMEMBER,[Historical Personnel].[Employee Id].[Employee Id]),
(
DIVIDE
(
SUM
(
DESCENDANTS([Period].[Fiscal Period].CURRENTMEMBER,[Period].[Fiscal Period].[Fiscal Period]),
[Measures].[FTE Active Utilization]*[Measures].[Work Days In Month]
)
,SUM(ROOT([Historical Personnel].[employee id].currentmember),[Measures].[Work Days In Month])
,0
)
)
);
//Use Weighted FTE for calculating the weighted value for each person (all periods aggregated)
//Forecast Billable End Of Year has default aggregation of last child
CREATE MEMBER CURRENTCUBE.[Measures].[Annualized CBH Projected]
AS DIVIDE
(
SUM
(
DESCENDANTS([Historical Personnel].[Employee Id].CURRENTMEMBER,[Historical Personnel].[Employee Id].[Employee Id]),
[Measures].[Billable Client Hours Current] *
(
DIVIDE
(
[Measures].[Forecast Billable End Of Year]
,
[Measures].[Forecast Billable FTE]
,0
)
)
*[Measures].[FTE MTD Active Utilization]
)
,[Measures].[FTE MTD Active Utilization]
,0
);
Simplified answer with the users filtering on the Is Active For Utilization flag is as follows:
//Weight FTE by employee calculating FTE * workdays for each period and then dividing by the sum of days irrespective of filters on historical personnel or miscellaneous
CREATE MEMBER CURRENTCUBE.[Measures].[FTE MTD]
AS SUM
(
DESCENDANTS([Historical Personnel].[Employee Id].CURRENTMEMBER,[Historical Personnel].[Employee Id].[Employee Id]),
(
DIVIDE
(
SUM
(
DESCENDANTS([Period].[Fiscal Period].CURRENTMEMBER,[Period].[Fiscal Period].[Fiscal Period]),[Measures].[Period FTE]*[Measures].[Work Days In Month]
)
,
SUM((ROOT([Historical Personnel].[employee id].currentmember),ROOT([Miscellaneous]),[Measures].[Work Days In Month]))
,0
)
)
);
//Weight by FTE with default agg for Forecast EOY being last child.
CREATE MEMBER CURRENTCUBE.[Measures].[Annualized CBH Projected]
AS DIVIDE
(
SUM
(
DESCENDANTS([Historical Personnel].[Employee Id].CURRENTMEMBER,[Historical Personnel].[Employee Id].[Employee Id]),
[Measures].[Billable Client Hours Current] *
(
DIVIDE
(
[Measures].[Forecast Billable End Of Year]
,
[Measures].[Forecast Billable FTE]
,0
)
)
*[Measures].[FTE MTD]
)
,[Measures].[FTE MTD]
,0
);

How to get last years qty in measure

How can I create a measure that has previous years Qty SHipped by month that will be used against a Current year measure showing a variance?
I want to take last years qty shipped minus the Plan(I already have this measure working) to get a variance. I have a dimension called dates that has a YY.
example calc..
[Measure].[pyqty] - [Measure].[Plan]
Thanks.
May help you something like this:
It calculates the QTD of the parallel previous period
WITH MEMBER [Measures].[Current QTD] AS
Sum
(
QTD([Date].[Calendar].CurrentMember)
,[Measures].[Internet Order Quantity]
)
MEMBER [Measures].[Last QTD] AS
Sum
(
YTD
(
ParallelPeriod
(
[Date].[Calendar].[Calendar Quarter]
,1
,[Date].[Calendar].CurrentMember
)
)
,[Measures].[Internet Order Quantity]
)
select {[Measures].[Current QTD],[Measures].[Last QTD]} ON 0
FROM [Adventure Works]
WHERE [Date].[Calendar].[Month].&[2005]&[11]
Take a o look at Time Calculations, in order to add time intelligence to your cube

Calculating Avg Orders per day using MDX

I am trying to create a calculated member which should returns the averages orders per week per person.
Below is the screen shot where the client will be looking to forecast the work load. Staff may not work all the days in a week.
The calculation will be : No of Orders / No of scheduled days in that week.
It would not be very hard to calculate this if the week name is in the same hierarchy of the date, but in this case it is not in hierarchy but just member of the dimension.
This is the MDX I've tried:
Avg ( Descendants
( [Date Planned].[Date Planned].CurrentMember, [Date Planned].[Date Planned].[Date Planned] ),
[Measures].[Orders Qty] )
It would be much easier when you have week and day added into the hierarchy, but if you don't have possibility to have this added, there is different non elegant solution.
If you would assume that this member will always be used with Week on rows your member calculation would be as follow:
This will work correctly only with weeks on rows - so I would recommend to extend your Calendar hierarchy by week and day and then we can have a chat about much more elegant solution.
Try using this:
WITH MEMBER [Measures].[avg_week] AS
Avg ( EXISTING { [Date Planned].[Week Of Year].[Week Of Year] },
[Measures].[Orders Qty] )
SELECT [Measures].[avg_week] ON COLUMNS,
NON EMPTY
{ [Person].[PersonName].[PersonName] * [Date Planned].[Week Of Year].[Week Of Year] } ON ROWS
FROM [Your cube]
Let me know if this can help you.
Maybe something like the following:
WITH
MEMBER [Measures].[PlannedDayCnt] AS
Count
(
Exists
(
(EXISTING
[Date Planned].[Date Planned].[Date Planned].MEMBERS)
,[Date Planned].[Week Of Year].currentmember
)
)
MEMBER [Measures].[Averge Orders] AS
[Measures].[Orders Qty] / [Measures].[PlannedDayCnt]
SELECT
{
[Measures].[Orders Qty]
,[Measures].[PlannedDayCnt]
,[Measures].[Averge Orders]
} ON 0
,
[Person].[PersonName].[PersonName]
* [Date Planned].[Week Of Year].[Week Of Year] ON 1
FROM [aCube];
I'd like to test but unsure how to model your scenario in the AdvWrks cube.
I would first want to see how many "dates" belong to the week. That would be easy as it would be those days when Orders were placed for that person that week.
NonEmpty
(
[Date Planned].[Date Planned].[Date Planned].MEMBERS,
(
[Date Planned].[Week Of Year].currentmember,
[Person].[PersonName].currentmember,
[Measures].[Orders Qty]
)
)
Now that you have the requisite dates for the "current" week and the "current" person, you would need to calculate the average order quantity for these set of dates. It would look like this:
AVG
(
NonEmpty
(
[Date Planned].[Date Planned].[Date Planned].MEMBERS,
(
[Date Planned].[Week Of Year].currentmember,
[Person].[PersonName].currentmember,
[Measures].[Orders Qty]
)
)
, [Measures].[Orders Qty]
)
Your final construct would need to be:
WITH MEMBER Measures.AverageOrderPerDay AS
AVG
(
NonEmpty
(
[Date Planned].[Date Planned].[Date Planned].MEMBERS,
(
[Date Planned].[Week Of Year].currentmember,
[Person].[PersonName].currentmember,
[Measures].[Orders Qty]
)
)
, [Measures].[Orders Qty]
)
SELECT
{
[Measures].AverageOrderPerDay,
[Measures].[Orders Qty]
}
ON 0,
[Person].[PersonName].[PersonName].MEMBERS
* [Date Planned].[Week Of Year].[Week Of Year].MEMBERS ON 1
FROM [YourCube]

How to view the first and/or last member values in a hierarchy

Is there a way for me to view the first and/or last leaf value in a level of a hierarchy?
I am trying to create a calculation dimension in SSAS which will include, for example, a year to date calculation which I would prefer not to display for dates in the future.
I've worked out how to make that happen at the lowest level (date), but am getting errors ath te aggregation levels when trying to implement the technique.
To help me accomplish what I want I've included a [Date In Past] member in my dimension, which contains a 0 if the date is in the past, and a if it is not.
For example this query, which returns calculations by date:
with member [Measures].[Year To Date] as
Sum(
{ IIF(strtovalue(
[Time Order Date].[Date In Past].Currentmember.membervalue
) = 0, null, [Measures].[Product Rev (with ship, no disc)]
) } *
PeriodsToDate(
[Time Order Date].[Fiscal Date].[Fiscal Year Name],
[Time Order Date].[Fiscal Date].CurrentMember
)
)
select
{[Measures].[Product Rev (with ship, no disc)],
[Measures].[Year To Date]} on 0,
[Time Order Date].[Date].Children on 1
from [Sales Analysis]
returns nulls in the [Year to Date] measure for all dates in the future.
This query, which returns calculations by the week:
with member [Measures].[Year To Date] as
Sum(
{ IIF(strtovalue(
[Time Order Date].[Date In Past].Currentmember.membervalue
) = 0, null, [Measures].[Product Rev (with ship, no disc)]
) } *
PeriodsToDate(
[Time Order Date].[Fiscal Date].[Fiscal Year Name],
[Time Order Date].[Fiscal Date].CurrentMember
)
)
select
{[Measures].[Product Rev (with ship, no disc)],
[Measures].[Year To Date]} on 0,
[Time Order Date].[Fiscal Week Name].Children on 1
from [Sales Analysis]
returns errors for all of the [Year To Date] values, I assume because there are more than one member in the week.
I would like to compare it with the last day of the week. How can I do that?
Thanks, --sw
To answer your question literally: Yes, you can get the first or last member of a set, and hence of a level, using the Head and Tail methods. Just note that these return a one-element set, hence you would often use Tail(something).Item(0).Item(0) to get a member.
However, as I understand your question, what you really need is to know if in the currently context, the member [Time Order Date].[Date In Past].[a] exists.
In that case, I would use
with member [Measures].[Year To Date] as
IIf(Intersect(EXISTING [Time Order Date].[Date In Past].[Date In Past].Members,
{[Time Order Date].[Date In Past].[a]}
).Count = 1,
NULL,
Sum(PeriodsToDate([Time Order Date].[Fiscal Date].[Fiscal Year Name],
[Time Order Date].[Fiscal Date].CurrentMember
)
[Measures].[Product Rev (with ship, no disc)]
)
)
select
{[Measures].[Product Rev (with ship, no disc)],
[Measures].[Year To Date]} on 0,
[Time Order Date].[Fiscal Week Name].Children on 1
from [Sales Analysis]
EXISTING gets the set of all Date In Past members that exist in the current context. And the intersection of that with the one-element set of member a has either 1 element (if a is member of the first set), or 0 elements (in case a is not contained in the set), which explains the condition for the IIf.

MDX PeriodsToDate Function

I am unable to get periodsToDate to work in MDX. I am getting the sum value when i am setting the periods to year level, but i am unable to get the sum values for quarters, months and days level.
This is my query for the year level (which is working fine).
With MEMBER [Measures].[Cumul Claim Cost] AS
'Sum
(
PERIODSTODATE
(
[Valuation Date].[Year].[All].Level,
[Valuation Date].[Year].CurrentMember
)
,[Measures].[Cost]
)'
select
{[Measures].[Cumul Claim Cost], [Measures].[Cost]} on columns,
{[Valuation Date].[Date].Members} on rows
from [WVWC DATA CUBE FROI SROI]
And this is my query for days level which is not working.
With MEMBER [Measures].[Cumul Claim Cost] AS
'Sum
(
PERIODSTODATE
(
[Valuation Date].[Year].[All].Level,
[Valuation Date].[Year].[Month-Year].[Quarter- Year].[Date].CurrentMember
)
,[Measures].[Cost]
)'
select
{[Measures].[Cumul Claim Cost], [Measures].[Cost]} on columns,
{[Valuation Date].[Date].Members} on rows
from [WVWC DATA CUBE FROI SROI]
Please help.
Thanks.
Nevermin guys, I was able to get the correct query after tons of hit and trials.
with MEMBER [Measures].[Cumul Claim Cost] AS 'Sum ( PERIODSTODATE (
[Valuation Date].[All].level,
[Valuation Date].CurrentMember ) ,[Measures].[Cost] )'
select {[Measures].[Cumul Claim Cost], [Measures].[Cost]} on
columns, NON EMPTY {[Valuation Date].[Quarter- Year]} on rows from
[WVWC DATA CUBE FROI SROI]