How to count a total percentage for calculated measure in MDX (Mondrian)? - mdx

I have a problem which looked like a simple requirement ... it turned out it wasn't ... at least for me.
At the moment I feel like I've read half of the MDX internet ...
I'm using latest Saiku CE (Mondrian 4), and my simplified cube looks like this:
Dimensions:
Machine.Manufacturer
Measures:
Measure.[Msg count]
Measure.[Distinct machines]
Measure.[Distinct days]
Calculated measures:
Measure.[Msg xMxD] which is basically: (Measure.[Msg count] / Measure.[Distinct machines] / Measure.[Distinct days]).
Measure.[Msg xMxd %] which is: (Measure.[Msg xMxD] / SUM(Measure.[Msg xMxD], Machine.[Manufacturer].[All Manufacturers]))
What I want to accomplish is this table:
But as you've probably guessed, I have a problem with the Measure.[Msg xMxd %] measure ...
Because it is calculated on base of another calculated measure, the % calculation is done after the summing for a particular Manufacturer and I don't know how to overcome this.
The closest answer I found was this one: https://forums.pentaho.com/threads/160265-Calculate-members-in-mdx/
... but this concerns only one generated member as a sum of all manufacturers.
I've found also some resolutions based on Axis(...) functions but those are unavailable in Mondrian.
Do you have any ideas ? Is there a possibility to generate a set of calculated members ? this would (at least theoretically) give me a possible to set solve order for all child members of [Machine].[Manufacturer]
Any help is much appreciated.

Related

Create custom count measure

I using an incident management cube to try to determine how many tickets were opened by a specific set of users. For instance, if there were 80,000 tickets opened - how many were opened by .[Submitter].&[xAutoData] and .[Submitter].&[xAutoVoice]?
Sounds pretty easy but I'm just learning MDX so this is a bit of an uphill battle. I'm thinking the best way is to use a custom measure but the closest I've got to any kind of result was by using this query.
WITH MEMBER [Measures].[AutoTickets] AS
COUNT({[INC - Incident Management].[Submitter].&[xAutoData],[INC - Incident Management].[Submitter].&[xAutoVoice]})
SELECT
{[Total Incidents],[AutoTickets]} ON 0,
{[INC - Incident Management].[Assigned Group]} ON 1
FROM [Incident Management Cube];
All it ever does is return '2' when there should be quite a bit more.
A point in the right direction would be appreciated and I think would help me learn what's going on behind the scenes.
Thanks!
EDIT:
Over the past few days, I've got a bit closer. I think I need to use a SUM function combined with an IIF.
Something like
WITH Member [Measures].[AutoTickets] AS
SUM(IIF([INC - Incident Management].[Submitter] = [INC - Incident Management].[Submitter].&[na\xData] OR
[INC - Incident Management].[Submitter] = [INC - Incident Management].[Submitter].&[na\xVoice],1,0))
But this returns an error. If I test the query without the SUM, the IIF part does work as expected so I think I'm missing one more piece on how I'm supposed to use the SUM function.
I think you need to clarify your question a little bit more in terms of what you want to achieve. From the query that you have provided, the calculated member "AutoTickets" counts only the set members of the [Submitter] attribute of [INC - Incident Management] dimension that you have provided with exact tuples and that number will always be 2 {xAutoData and xAutoVoice} across all dimensions, it's like a constant.
Suppose that you want to know how many [Submitter]'s contributed to the Total Incident measure, than I suggest that you try the following statement:
WITH MEMBER [Measures].[AutoTickets] AS
COUNT(NonEmpty({[INC - Incident Management].[Submitter].Members),([Measures].[Total
Incidents])})
SELECT
{[Total Incidents],[AutoTickets]} ON 0,
{[INC - Incident Management].[Assigned Group]} ON 1
FROM [Incident Management Cube];
Supposing that you have a measure "[Measures].[TicketCount]" which gives the count of tickets, the below query would give you tickets for
"[Submitter].&[xAutoData] and .[Submitter].&[xAutoVoice]". You just replace with the relevant measure.
select [Measures].[TicketCount] on columns,
{[INC - Incident Management].[Submitter].&[xAutoData],[INC - Incident Management].[Submitter].&[xAutoVoice]}
on rows
from [Incident Management Cube]

Median calculated in MDX SSAS

here is my case. I have small training in creating OLAP cube in SSAS and as part of it I need to calculate median time from creation issue to resolve issue.
So according to microsoft docs I should use MEDIAN function in MDX. So here is my code:
MEDIAN([Issue].[Issue ID],[Measures].[Hours Resolved])
Short explanation: [Measures].[Hours Resolved] it's a measure calculated in database from dimensions "resolved issue time" - "creation issue time" with DATEDIFF function. Both are smalldatetime datatype.
And it looks like it works in proper way for case on the screen below.
Exept "Grand Total" value in Mediana column.
I believe that Grand Total value should be 12 becasue this is proper score according to way the median should be calculated (checked also in Excel). So am I wrong here and this is proper behaviour? Or maybe I miss something in my calculation or configuration in SSAS?
Second case in this exercise.
When I will add for example Group Name column like on the picture below:
In my understanding value mediana column for let's say CRM part should be 9.
Can you please guide me if I'm right or wrong? If I'm right how to achieve this. Or if I'm wrong please point mistake in my solution. This is my 1st time when I'm calculating median.
It's a little embrassing that no one even look at it - 16 views and probably all mine - well doesn't matter anymore because I figured it out myself.
For proper median calculation for all dimensions I should use Median function and Scope function in MDX. So here is the code if someone will face the same problem in future:
CREATE MEMBER CURRENTCUBE.[Measures].[Median]
AS Null
VISIBLE = 1;
SCOPE([Measures].[Median]);
THIS = MEDIAN([View Issue Median].[Issue ID].[Issue ID], [Measures].[Hours Resolved]);
END SCOPE;

Weighted Average in MDX sums measures before multiplying

I have a calculated member that looks like this:
Asian Weighted = ([Measures].[Asian] * [Measures].[Population])
My MDX query looks like this:
WITH
MEMBER [Measures].[AsianPop] AS
(([Measures].[Asian Weighted], [Jurisdiction.BTA].[BTA].&[51]) / ([Jurisdiction.BTA].[BTA].&[51], [Measures].[Population]))
SELECT
{[Measures].[AsianPop]} ON 0
FROM
[Selection Statistics]
The problem is in the numerator. Asian and Population are both SUMMED before they are multiplied together. Is there a straightforward way to do a weighted average in MDX?
The solution that you described in your comment - pre-caclulating the measure to sum - is the best approach. In theory, you could implement the correct calculation purely in MDX, but this is complex and in many cases - at least in Analysis Services, I have no experience with Mondrian - really slow. You would have to instruct the MDX engine explicitly to do the multiplication on leaf level, and then aggregate. You could use functions like Leaves or Descendants to go to leaf level. You would have to think about the attributes for which you need to go down to leaf level, and for which attributes this may not be necessary. My assumption - as far as Analysis Services is concerned - is that as this uses a custom aggregation, all the built in aggregations which make the cube fast are not used.

LastChild simulation in MDX - Multiple hierarchies

I have a SSAS cube in which there is a measure that needs to be allocated via a percentage located in another measure. I have all this set up as a Measure Expression in my "Equity Amount" measure and it works great.
My problem is that this "Equity Amount" measure is actually a snapshot so I would need it to aggregate using the LastChild function. It turns out that you cannot have a measure expression in a semi additive measure so i'm trying to fake the LastChild function in MDX.
I've seen a lot of examples everywhere on the web and all but none of them talk about having multiple hierarchies in the date dimension. I have both "calendar Year" and "Fiscal Year" hierarchies.
My MDX works for one hierarchy but as soon as I scope for the second hierarchy, the first one gets overwritten. I'm guessing I need to treat both hierarchies in a single statement but am having a real tough time getting it to work.
Here is my MDX for one hierarchy. Can anyone help modify it for multiple hierarchies or is there any other way to solve my problem ?
Scope([Measures].[Equity Value]);
This = iif(isleaf([Calendar].[By Calendar Year].CurrentMember),
[Measures].[Equity Value],
([Calendar].[By Calendar Year].CurrentMember.LastChild,[Measures].[Equity Value]));
End Scope;
David,
1) You're using scope as a calculated member. You can get rid of your iif by declaring the scope working only in a sub-cube :
scope ([Measures].[Equity Value],[Calendar].[By Calendar Year].levels(0).... )
This = (the expression)
2) Not sure to understand your problem but a tuple with two members of two hierarchies of the same dimension can be null by construction: As an example your first day of the calendar (1/1/2010) and the first day of your fiscal calendar (e.g. 1/6/2020) are not the same day so actually null. Two hierarchies of a same dimension are only ways of representing the same coordindates (here days), you're doing an intersection by declaring a tuple.
Not sure I'm helping you...
Thanks for trying! I understand what you mean (I think). MDX is one tough language!
I ended up doing the allocation via the view that is the source for my measure and keeping the LastChild aggregation function for the measure. In the end, it is much easier and also is better for query performance.
Thanks anyway :)

Multiplying Quantity * Price in Calculated Member

I know MDX is used for much more sophisticated math, so please forgive the simplistic scenario, but this is one of my first Calculated members.
When I multiply Price x Quantity, the AS cube's data browser has the correct information in the leaf elements, but not in any of the parents. The reason seems to be that I want something like (1 * 2) + (2 * 3) + (4 * 5) and not (7 * 10) which think I am getting as a result of how the Sum is done on columns.
Is the IsLeaf expression intended to be used in these circumstances? Or is there another way? If so, are there any examples as simple as this I can see?
This Calculated member that I tried to create is just this:
[Measures].[Price]*[Measures].[Quantity]
The result for a particular line item (the leaf) is correct. But the results for, say, all of april, is an incredibly high number.
Edit:
I am now considering that this might be an issue regarding bad data. It would be helpful though if someone could just confirm that the above calculated member should be work under normal circumstances.
Here it is a blog post dealing with this particular problem: Aggregating the Result of an MDX Calculation Using Scoped Assignments.
For leaf level computations resulting in something that can then be summed, MDX is rather complex and slow.
The simplest way to do what you want to achieve would be to make this a normal measure, based on the Price x Quantity calculation defined in the data source view.