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

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
);

Related

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

MDX queries in SSMS vs calculated membersin cubes performance

I have some MDX queries with calculated members than when I run them in SSMS run very fast.
But when I implement these calculated members in the cube and run them, it's very slowly.
Any ideas of this behavior?
This is the query that runs smoothly in SSMS, but it takes forever when I query the cube from Excel or Tableau (against the same calculated members in the Cube)
with member [Measures].[Sales BUM Avg 3Months]
as
sum(
lastperiods(3, ancestor([Date].[Calendar].currentMember,[Date]. [Calendar].[Calendar Year Month])), [Measures].[Sales Month BUM]
)
/
count(
nonempty(lastperiods(3, ancestor([Date].[Calendar].currentMember,[Date].[Calendar].[Calendar Year Month])), [Measures].[Sales Month BUM])
)
member [Measures].[CoverageSalesBUM]
as
sum([Measures].[Unrestricted BUM])
/
sum([Measures].[Sales BUM Avg 3Months] )
select non empty { [Measures].[Unrestricted BUM] , [Measures].[Sales BUM Avg 3Months] } on 0
,non empty([Date].[Calendar].[Calendar Date] , [Plant].[Plant].[Plant],[Material].[Material].[Material].[149249] ) on 1
from [InventCoverage]
(More of a code review than an answer, as I don't know much about cube scripts so cannot comment on what you might need to do to the cube)
Is you first calculation not a re-invention of the function Avg?
Also in you second calc why do you need to apply Sum()? If this is the aggregation set in the cube then no need to explicitly say Sum. Also apparently Divide is quite a recent introduction and maybe marginally more efficient
WITH
MEMBER [Measures].[Sales BUM Avg 3Months] AS
Avg
(
LastPeriods
(3
,Ancestor
(
[Date].[Calendar].CurrentMember
,[Date].[Calendar].[Calendar Year Month]
)
)
,[Measures].[Sales Month BUM]
)
MEMBER [Measures].[CoverageSalesBUM] AS
Divide
(
[Measures].[Unrestricted BUM]
,[Measures].[Sales BUM Avg 3Months]
)
SELECT
NON EMPTY
{
[Measures].[Unrestricted BUM]
,[Measures].[Sales BUM Avg 3Months]
} ON 0
,NON EMPTY
(
[Date].[Calendar].[Calendar Date]
,[Plant].[Plant].[Plant]
,[Material].[Material].[Material].[149249]
) ON 1
FROM [InventCoverage];

Count Working Days MDX

I would like to count the working days of a spesific time range and then find the Average Daily Dispatches.Currently the time range is at WHERE statement.
I believe that I have include the date range in the 1st Member but I can't figure how to count the dates in a month range.
Any suggestments?
WITH MEMBER [Measures].[Working Days] AS
COUNT(Date.[Working Date].&[1])--Doesn't work
MEMBER [Measures].[Average Daily Dispatches] AS
[Measures].[Total Dispatches]/[Measures].[Working Days]
SELECT [Measures].[Average Daily Dispatches] ON 0
FROM [cube]
WHERE (
[Date].[Month].&[2015-01-01T00:00:00]:[Date].[Month].&[2015-08-01T00:00:00]
);
Use the NonEmpty function to yield those working dates on which there was a dispatch. Then use COUNT on top of this.
WITH MEMBER [Measures].[Working Days] AS
COUNT
(
NonEmpty
(
[Date].[Working Date].MEMBERS,
[Measures].[Total Dispatches]
)
)
Some sort of alternative seems to exist using Exists/Existing (I think 1 is Monday in the AdvWrks cube!)
WITH
MEMBER [Measures].[MondayCnt] AS
Count
(
Exists
(
(EXISTING
[Date].[Calendar].MEMBERS)
,[Date].[Day of Week].[1]
)
)
MEMBER [Measures].[Averge] AS
[Measures].[Internet Sales Amount] / [Measures].[MondayCnt]
SELECT
{
[Measures].[Internet Sales Amount]
,[Measures].[MondayCnt]
,[Measures].[Averge]
} ON 0
,
[Date].[Calendar].[Month].&[2006]&[6]
:
[Date].[Calendar].[Month].&[2007]&[6] ON 1
FROM [Adventure Works];
The above results in the following:

How to calculate average based on distinct counts in MDX

My SSAS cube has the following fact and dimensions with the columns as shown below
FactActivity
DateKey, UserKey, ActivityKey, ActivityCount
DimDate
DateKey, Date, Week, Year
DimUser
UserKey, UserName, Gender
DimActivity
ActivityKey, ActivityName
I have created the distinct count measures of users and dates as follows
[Distinct Users]
COUNT(NONEMPTY([DimUser].[UserKey].[UserKey].Members, [Measures].[ActivityCount])
[Distinct Dates]
COUNT(NONEMPTY([DimDate].[DateKey].[DateKey].Members, [Measures].[ActivityCount])
Both these measures are working correctly as expected when I slice/pivot by ActivityName.
Now I wanted to calculate average days per user, so I created the metric as follows
[Avg Days Per User]
AVG([DimUser].[UserKey].[UserKey].Members, [Measures].[Distinct Dates])
But this is giving me wrong results.! i also tried
DIVIDE([Measures].[Distinct Days], [Measures].[Distinct Users])
Still I get wrong results...what i'm doing wrong?
Maybe just adding in EXISTING will help?
AVG(
EXISTING [DimUser].[UserKey].[UserKey].Members,
[Measures].[Distinct Dates]
)
Although trying to recreate something similar in AdvWks I seem top get a valid return without EXISTING:
WITH
MEMBER [Measures].[Avg Count Per Reseller] AS
Avg
( [Reseller].[Reseller].[Reseller].MEMBERS
,[Measures].[Reseller Order Count]
), format_string = "0.0000"
SELECT
{[Measures].[Reseller Order Count],[Measures].[Avg Count Per Reseller]} ON 0
,{[Promotion].[Promotion].[All Promotions].Children} ON 1
FROM [Adventure Works]
WHERE [Date].[Calendar Year].&[2005];

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]