Aggregation of an MDX calculated measure when multiple time periods are selected - ssas

In my SSAS cube, I've several measures defined in MDX which work fine except in one type of aggregation across time periods. Some don't aggregate (and aren't meant to) but one does aggregate but gives the wrong answers. I can see why, but not what to do to prevent it.
The total highlighted in the Excel screenshot below (damn, not allowed to include an image, reverting to old-fashion table) is the simplest case of what goes wrong. In that example, 23,621 is not the grand total of 5,713 and 6,837.
Active Commitments Acquisitions Net Lost Commitments Growth in Commitments
2009 88,526 13,185 5,713 7,472
2010 92,125 10,436 6,837 3,599
Total 23,621 23,621
Active Commitments works fine. It is calculated for a point in time and should not be aggregated across time periods.
Acquisitions works fine.
[Measures].[Growth in Commitments] = ([Measures].[Active Commitments],[Date Dimension].[Fiscal Year Hierarchy].currentMember) - ([Measures].[Active Commitments],[Date Dimension].[Fiscal Year Hierarchy].prevMember)
[Measures].[Net Lost Commitments] = ([Measures].[Acquisitions] - [Measures].[Growth in Commitments])
What's happening in the screenshot is that the total of Net Lost Commitments is calculated from the total of Acquisitions (23,621) minus the total of Growth in Commitments (which is null).
Aggregation of Net Lost Commitments makes sense and works for non-time dimensions. But I want it to show null when multiple time periods are selected rather than an erroneous value. Note that this is not the same as simply disabling all aggregation on the time dimension. The aggregation of Net Lost Commitment works fine up the time hierarchy -- the screenshot shows correct values for 2009 and 2010, and if you expand to quarters or months you still get correct values. It is only when multiple time periods are selected that the aggregation fails.
So my question is how to change the definition of Net Lost Commitments so that it does not aggregate when multiple time periods are selected, but continues to aggregate across all other dimensions? For instance, is there a way of writing in MDX:
CREATE MEMBER CURRENTCUBE.[Measures].[Net Lost Commitments]
AS (iif([Date Dimension].[Fiscal Year Hierarchy].**MultipleMembersSelected**
, null
, [Measures].[Acquisitions] - [Measures].[Growth in Commitments]))
ADVthanksANCE,
Matt.

A suggestion from another source has solved this for me. I can use --
iif(iserror([Date Dimension].[Fiscal Year Hierarchy].CurrentMember),
, null
, [Measures].[Acquisitions] - [Measures].[Growth in Commitments]))
CurrentMember will return an error when multiple members have been selected.

I didn't understand much of the first part of the question, sorry...but at the end I think you ask how to detect if multiple members from a particular dimension are in use in the MDX.
You can examine either of the two axes as a string, and use that to form a true/false test. Remember you can use VBA functions in Microsoft implementations of MDX.
I suggest InStr(1, SetToStr(StrToSet("Axis(1)")), "whatever") = 0 as a way to craft the first argument of your IIF.
This gets the set of members on axis number one, converts it to a string, and looks to see if a certain string is present (it returns the position of that string within the other). Zero means not found (so it returns true). You may need to use axis zero instead, or maybe check both.
To see if multiple members from the same dimension were used, the test string above would have to be more complicated. You want to know if whatever occurs once or twice. You could test if the first occurance of the string was at the same position as the last occurance (by searching backwards); though that could also mean the string wasn't found at all:
IIF(
InStr(1, bigstring, littlestring) = InStrRev(bigstring, littlestring),
'used once',
'used twice or not at all'
)

I came across this post while researching a solution for my own issue with grand totals of calculated measures over time when filters are involved. I think you could have fixed the calculations instead of suppressing them by using dynamic sets. This worked for me.

Related

TABLEAU Totals not matching what's in view

I've been dealing with this issue in various ways throughout my time with this dataset in Tableau.
As you can see, the Total count of properties for each city is including properties that have been successfully filtered out of view. Why? The dyn.RANKED Profitable Investments (grouped) variable on the Filter shelf is an attempt to double down on the same as the first line of the Calculated Field - to ignore the unwanted properties in each city. The view ignores them, but the totals do not.
If the Watershed Property pill is removed from the Rows shelf, then the dyn.NumProps_in_City results shown on the table are each the same as the Totals you see here (i.e., despite the first line of the calculated field, properties that do not meet that opening condition are being counted)...despite the view with the Watershed pill knowing not to show them.
Also if the Watershed Property pill is removed from the Rows shelf, then the dyn.RANKED Profitable Investments (grouped) variable on the Filter shelf suddenly only has one category to choose from (i.e., 'INVEST') if you go to edit the filter. Which would be great since that's the category I care about, but not if the counts are including things that are not in that category despite the filter.
Messing around with Include, Exclude, and Fixed in the calculated field doesn't seem to work here since I can't figure out how to get around various aggregate/non-aggregate and/or ATTR errors no matter where I place them. Plus, my incorrect counts are not suffering from an LOD issue - the LOD is correct - it's an issue of not consistently filtering out the unwanted rows at the desired LOD.
Please advise!
Thanks,
Christian
It seems that dyn.Ranked calculated field calculates the value prior to filtering. This may happen if you have used any LOD calculations in the syntax.
Simply right click such fields on filters shelf and click add to context. This will cause LOD calculations to calculate after the filtering.
see this link, the context filters are above the LOD calculations, in order of precedence; but measure filters are below the LOD calcs. Therefore if measures are used as filters, these have to be added to context so that their order of precedence is above such calculations

Can someone explain the following Essbase code: FIX, #relative

Can someone please explain the below Essbase code to me please? This is my first time looking at any Essbase code and I'm getting a bit confused as to what it is actually doing.
FIX(&Mth, &Yr, &Version,
"Sector1","Sector2", #relative("Source Code",0), #relative("Channel", 0) )
FIX("AccountNo","DepNo")
DATACOPY "1A11"->"A-500" TO "1BCD"->"C-800";
ENDFIX
ENDFIX
From what I have googled the following is my understanding:
Creates a new command block which restricts database calculations to this subset.
Passes the following members into the command to be used:
Mth
Yr
Version
Returns the following fields:
Sector1
Sector2
returns the 0-level members of the Source Code member - meaning it returns the members of the Total Source Code without children (no other dimensions)
returns the 0-level members of the Channel member - meaning it returns the members of the Channel without children (no other dimensions)
Begins a new command block and passes the following members into the command to be used:
AccountNo
DepNo
Copies the range of cells 1A11, A-500 over to the range 1BCD, C-800
The above is what I understand from the oracle documents on each of the functions, but I can't actually figure out what is happening.
Welcome to the world of Essbase; it can be a little daunting at first especially if you're new to the concept of multidimensionality. You are on the right track regarding analyzing your calc script.
Try not to think of the FIX statement as a command block, per se. A FIX is used to select a portion of cells in the cube. Every single piece of data in your cube has a particular address that consists of one member from every dimension, plus the actual data value itself. For instance, a cube with the dimensions Time, Year, Scenario, and Location might have a particular piece of data at Jan->2018->Actual->Washington. The number of possible permutations of data in a cube can quickly get very large. For instance, if you're organization has 4 years of data, 12 months in a year, 100 locations, 10000 accounts, 3 versions, and 10 departments, you are talking about 4 * 12 * 100 * 10000 * 3 * 10 = 1.4 billion different potential addresses (cells) of data – and that's actually fairly small for a cube, as they tend to grow much larger.
That said, FIX statements are used to narrow down the scope of your calculation operation, rather than operating on the ENTIRE cube (all 1.4 billion cells in my hypothetical example), the FIX essentially restricts the calculation to cells that match certain criteria you specify. In this case, the first FIX statement restricts the calculation to a particular month, yr, version, sectors, sources, and channels. Note that the ampersand on Mth, Yr, and Version means that a substitution variable is to be used. This means your server or cube has a substitution variable value set, such as the variable Mth = "Jan" and Yr = "FY2018" and Version might be "Working" or "Final" or something similar. I would guess that Sector1 and Sector2 are possibly two different members from the same dimension. #RELATIVE("Source Code", 0) is a function that finds the level-0 members (leaf/bottom-level members in a dimension, that is, members that do not have children below them) of the specified member.
In other words, the first FIX statement is narrowing the scope of the calculation to a particular month in a particular year in a particular version (as opposed to all months, all years, all versions), and for that particular month/year/version (for either Sector1 or Sector2) it is fixing on all of the level-0/bottom/leaf members in Source Code and Channel dimensions.
The next FIX statement just further narrows the current scope of cells to calculate on in addition to the outer FIX. It's not uncommon to see FIX statements nested like this.
Lastly we get to the part where something actually happens: the DATACOPY. In the given FIX context, this DATACOPY command is saying that for EACH cell in the current FIX, copy values from the source to the destination. DATACOPY is a little more straightforward when it's just DATACOPY "Source" TO "Target" as opposed to using the inter dimensional operator (->)... but this is perhaps more easily understood in terms of the time/year dimensions. For example, imagine the data copy was written like this:
DATACOPY "FY2018"->"Dec" TO "FY2019"->"Jan";
In this DATACOPY I'd be telling Essbase that for the given FIX context I would like to copy values from the end of the year (data values where the year is FY2018 AND the month is Dec) to the beginning of the next year (data values where the year is FY2019 AND the month is Jan). Your DATACOPY is working in a similar fashion, but using cost centers or something else. It all just depends on how the cube is setup.

Qlikview: Total of calculated metric based on calculated dimension

I started working on Qlikview a week back and I am working on this dashboard.
I have a particular requirement which I am not able to achieve:
So, I have a calculated dimension "Categories" added in my script which based on certain conditions tags each name as SLEEPERS,STARS,WEAKLINKS etc.
Now, I have flagged the names based on certain condition which works fine.
The issue is, I want the sum of those flags on the level of calculated dimension CATEGORIES(SLEEPERS, STARS..etc) and my month field.
I am not able to achieve it because, the flag itself is a calculated field so sum of calculated field doesn't work. I tried using aggr, function but it returns zero for all rows. I am not sure why. in the aggr function I use the sum(Aggr(Flag,MONTH,Categories))
Can someone suggest a work around for this? I have attached the screenshot of the report for better understanding of the requirement

DAX sum different DateTime

I have a problem here, i would like to sum the work time from my employee based on the data (time2 - time 1) daily and here is my query:
Effective Minute Work Time = 24. * 60 * (LASTNONBLANK(time2,0) -FIRSTNONBLANK(time1,0))
It works daily, but if i drill up to weekly / monthly data it show the wrong sum as it shown below :
What i want is summary of minute between daily different times (time2-time1)
Thanks for your help :)
You have several approaches you can take: the hard way or the easier way :). The harder (at least for me :)) is to use DAX to do this. You would:
1) create a date table,
2) Use the DAX calculate function to evaluate your last non-blank and first non-blank values (you might need to use calculate table, but I'm not sure; DAX experts jump in). Then subtract one vs. the other.
This will give you correct values for a given day for a given person. You can enforce the latter condition by putting a 'has one value' guard on the person name so that your measure informs the report author if they're not using it right.
Doing the same for dates is a little trickier. In the example you show you are including the date in the row grouping. But if you change your mind and want instead to have 'total hours worked by person' or 'total hours worked by everyone' you're not done with modelling yet.
Your next step is to use calculate table in combination with calculate to create a measure that returns the total. You'll use calculate table so you evaluate each date and the hours worked on that date by person. Then you'll use calculate to summarize that all down to a single number. If you're not careful with your DAX (or report authoring) you might mix which person you're summarizing for so that your first/last non blank are not at the person level. It gets intense quickly.
Your easier solution, though it might be more limited in its application - depends really on your scenario - is to use the query to transform the data into a summary by day and person using the group by command. This will give you a row per person per day with their start and end times. Then you can quickly calculate the hours worked on that day. Then you can quite easily build visuals on top of the summary data. Of course you give up some of the flexibility of the having a proper data model. However if you have a date table, a person table, and your summary table and then setup your relationships correctly you can achieve answers to the most common questions.

Running Total With Multiple Hierarchies

I have a date dimension that has multiple hierarchies (as most do). I have a number of measures that are calculated as a running total, as shown in the example below.
AGGREGATE([Date].[Calendar].[Date].Members.Item(0):ClosingPeriod([Date].[Calendar].[Date], [Date].[Calendar].CurrentMember), [Measures].[Number Of Contracts])
My problem is that the running total only works for the Calendar hierarchy (which breaks everything down by year, month, and then day). If I instead use the Weeks hiearchy (which breaks things down by individual week), the calculation doesn't work, it just shows the same number for every week.
Is there a performant way in MDX to make the running total work for multiple hierarchies? Everything I've attempted so far has been quite slow.
One possible solution is below. By using the EXISTING keyword, one can get a list of all the Date members that exist in the current context, and then use those dates to define a range over which to aggregate the data. Based on my initial testing, the performance is similar to the calculation in the question.
AGGREGATE(NULL:TAIL(EXISTING [Date].[Date].[Date].Members).Item(0), [Measures].[Number Of Contracts])
Another, possibly more performant, solution is described at http://www.purplefrogsystems.com/blog/2010/08/mdx-calculated-member-spanning-multiple-date-dimensions/. It solves the problem by calculating ranges for all applicable hierarchies and then crossjoining those hierarchies together.
AGGREGATE({ NULL:[Date].[Calendar].CurrentMember } * { NULL:[Date].[Week].CurrentMember })
The only drawback of this solution is that it can become verbose if you have many hierarchies that do not have attribute relationships between eachother.