I tried doing it in MDX but to no avail, therefore I had to use the SSAS User Defined Function to calculate the Avg of Max. The set to calculate Avg
(DateSet
) across, set to calculate Max
across (TimeSet
) and a third set to containing the records to be excluded in Max
operation, are passed as parameters to the UDF.
The basic code is like (presenting the coded Avg of Max functionality, excluding error checking):
public static class AvgOfMaxMethods
{
public static double AvgOfMax(Set maxAcrossSet, Set avgAcrossSet, Set setToExclude, Expression measureExpression)
{
var setToExcludeQueryable = setToExclude.Tuples.OfType<Microsoft.AnalysisServices.AdomdServer.Tuple>();
IList<double> maxMembers = new List<double>();
foreach(var avgAcrossTuple in avgAcrossSet.Tuples)
{
var max = double.MinValue;
foreach(var maxAcrossTuple in maxAcrossSet.Tuples)
{
if (!setToExcludeQueryable.Any(tuple => tuple.Members[0].UniqueName.Equals(avgAcrossTuple.Members[0].UniqueName) && tuple.Members[1].UniqueName.Equals(maxAcrossTuple.Members[0].UniqueName)))
{
TupleBuilder tb = new TupleBuilder(avgAcrossTuple.Members[0]);
tb.Add(maxAcrossTuple.Members[0]);
var calculatedVal = measureExpression.Calculate(tb.ToTuple()).ToDouble();
max = calculatedVal > max ? calculatedVal : max;
}
}
if (!max.Equals(double.MinValue))
{
maxMembers.Add(max);
}
}
return maxMembers.Average();
}
}
An with this the query becomes (keeping the original Max
and StDev
for comparison):
WITH
MEMBER MaxMember as MAX(TimeSet, [Measures].[Value])
MEMBER AvgOfMax as Avg(DateSet, MAX(TimeSet, [Measures].[Value]))
MEMBER StDevOfMax as StDev(DateSet, MAX(TimeSet, [Measures].[Value]))
Member MaxFromUDF as UDFPoc.UDFPoc.AvgOfMaxMethods.AvgOfMax(TimeSet, DateSet, SetToExclude, [Measures].[Value])
SET DateSet as EXISTING [Dim Date].[Date Id].[Date Id]
SET TimeSet as EXISTING [Dim Time].[Time Id].[Time Id]
SET SetToExclude as {[Dim Date].[Date Id].&[20150103] * [Dim Time].[Time Id].&[1] : [Dim Time].[Time Id].&[2]}
select
{
[Measures].[Value], MaxMember, AvgOfMax, StDevOfMax, MaxFromUDF
}
on 0,
{
DateSet * TimeSet
} on 1
FROM
(
SELECT ({[Dim Date].[Date Id].&[20150101] : [Dim Date].[Date Id].&[20150103]}, {[Dim Time].[Time Id].&[1] : [Dim Time].[Time Id].&[4]})
on 0
FROM [Test Date Time Dimensions]
)
And the results look like (here tuples of the excluded set is highlighted in red):
As can be seen, the UDF excludes the members of each tuple in the SettoExclude
set when calculating Max
and Average
. Now correct average considering the excluded set is being calculated, as can be seen in the image. Similarly StDev
can be calculated in this manner.
See this as a guide to create SSAS User Defined Functions.
Best Answer
Assuming then, that you are going to add (or derive) another column for DatabaseName (or source name) then this should work for you.