How do I reuse a created member throughout an MDX statement? - mdx

I have a bunch of calculated members that I need to create which are referenced off a single date.
Rather than repeating the MDX that gets the date member for which the measure will be based off, is there a way to create the date member at the start, and then reference it throughout so that I don't have to repeat the MDX multiple times? I was thinking something like the below however it returns a NULL:
WITH MEMBER [Date].[Retail].[Closing Date] AS
IIF (
[Date].[Retail].CurrentMember.Level.Name = 'Date',
[Date].[Retail].CurrentMember.PrevMember,
[Date].[Retail].CurrentMember
)
MEMBER [Measures].[Closing New] AS
(
[Date].[Retail].[Closing Date],
[Measures].[On Hand Quantity]
)
SELECT
[Date].[Retail].[Date].Members ON ROWS,
{
[Measures].[On Hand Quantity],
[Measures].[Closing New]
} ON COLUMNS
FROM
Retail
WHERE
[Date].[Retail Year].&[2017]
As above, I want to use the Closing Date member multiple times for various calculations.

To investigate why it is returning null try something like the following to see if it is as you expect:
WITH
MEMBER [Measures].[nm] AS
[Date].[Retail].CurrentMember.Level.Name
SELECT
{
[Measures].[On Hand Quantity],
[Measures].[nm]
} ON 0,
[Date].[Retail].[Date].Members ON 1
FROM Retail
WHERE [Date].[Retail Year].&[2017];
(I also switched the declaration order inside the SELECT clause as it is standard to declare columns, as it is axis 0, first followed by rows)

Why yes, there is!
the pattern I follow here is to create a set of one member then reference the first item of that set.
with set currentDate as
[Date].[Retail].[Date].&[20160725]
then reference it in the remainder of your query as
currentDate.item(0)

Related

MDX Calculated member SUM with OR

I inherited some mdx code which uses calculated members and the sum function. I need to make a new member using SUM but and OR (union?) set. I have tried various syntaxes but they all error.
I have code as below:
-- uses this date filter
set [as_of_month] as {strtomember("[Date].[Year - Month].[Month].&[" + cstr(format(cdate("Jul 2019"),"yyyy-MM")) + "-01T00:00:00]")}
-- member 1
member [SIONLY_MTH] as sum([as_of_month] * [Incident Details].[Is SI].[Is SI], [Measures].[Environment Impact Count])
-- member 2
member [MajorNC_Month] as sum([as_of_month] *
[Impact].[Impact].&[3] *
[Non Compliance].[Non Compliance Type].&[Major non-compliance],
[Measures].[Non Compliance Count]) + 0
-- I need a new member which is an OR of the previous 2, ie, count of
-- SI_ONLYMONTH or [MajorNC_Month] filtered by [as_of_month]
member [LegalSI_EnvSI_Month] as SUM([as_of_month] * {[Incident Details].[Is SI].[Is SI] , [Non Compliance].[Non Compliance Type].&[Major non-compliance]}
, [Measures].[Environment Impact Count]) + 0
The set inside the last sum function doesnt work, it returns #Error.
Does anyone know how to use a unioned set as the argument to the SUM function in mdx?
Thanks
Your problem basicly deals with the concepts of dimensionality and hierarchility
Try this
sum(
{
([as_of_month] * [Incident Details].[Is SI].[Is SI][Impact].[Impact].defaultmember[Non Compliance].[Non Compliance Type].defaultmember),
([as_of_month] * [Incident Details].[Is SI].defaultmember*[Impact].[Impact].&[3]*[Non Compliance].[Non Compliance Type].&[Major non-compliance])
}
,
[Measures].[Environment Impact Count])
Edit: Includes explanation on how and why the above query works.
In your problem you have two sets that have diffrent hierarchies in them. So you have to balance them. Lets take a look at your first set
sum([as_of_month] * [Incident Details].[Is SI].[Is SI],
[Measures].[Environment Impact Count])
This doesnt explicitly include "[Impact].[Impact]" however before executing SSAS takes the liberty to include [Impact].[Impact].defaultmember in the query. Based on this fact I balanced both of your sets by expicitly including the default members of attribute hierarchies that were orignally not part of your Set.
Next I encapsulaed them in "()" to indicate that they are a tuple of a larger Set.Then both these tuples are encapsulated in "{}" like this "{(tuple1),(tuple2)}"

Calculated SSAS Member based on multiple dimension attributes

I'm attempting to create a new Calculated Measure that is based on 2 different attributes. I can query the data directly to see that the values are there, but when I create the Calculated Member, it always returns null.
Here is what I have so far:
CREATE MEMBER CURRENTCUBE.[Measures].[Absorption]
AS sum
(
Filter([Expense].MEMBERS, [Expense].[Amount Category] = "OS"
AND ([Expense].[Account Number] >= 51000
AND [Expense].[Account Number] < 52000))
,
[Measures].[Amount - Expense]
),
VISIBLE = 1 , ASSOCIATED_MEASURE_GROUP = 'Expense';
Ultimately, I need to repeat this same pattern many times. A particular accounting "type" (Absorption, Selling & Marketing, Adminstrative, R&D, etc.) is based on a combination of the Category and a range of Account Numbers.
I've tried several combinations of Sum, Aggregate, Filter, IIF, etc. with no luck, the value is always null.
However, if I don't use Filter and just create a Tuple with 2 values, it does give me the data I'd expect, like this:
CREATE MEMBER CURRENTCUBE.[Measures].[Absorption]
AS sum
(
{( [Expense].[Amount Category].&[OS], [Expense].[Account Number].&[51400] )}
,
[Measures].[Amount - Expense]
),
VISIBLE = 1 , ASSOCIATED_MEASURE_GROUP = 'Expense';
But, I need to specify multiple account numbers, not just one.
In general, you should only use the FILTER function when you need to filter your fact table based on the value of some measure (for instance, all Sales Orders where Sales Amount > 10.000). It is not intended to filter members based on dimension properties (although it could probably work, but the performance would likely suffer).
If you want to filter by members of one or more dimension attributes, use tuples and sets to express the filtering:
CREATE MEMBER CURRENTCUBE.[Measures].[Absorption]
AS
Sum(
{[Expense].[Account Number].&[51000]:[Expense].[Account Number].&[52000].lag(1)} *
[Expense].[Amount Category].&[OS],
[Measures].[Amount - Expense]
),
VISIBLE = 1 , ASSOCIATED_MEASURE_GROUP = 'Expense';
Here, I've used the range operator : to construct a set consisting of all [Account Number] members greater than or equal to 51000 and less than 52000. I then cross-join * this set with the relevant [Amount Category] attribute, to get the relevant set of members that I want to sum my measure over.
Note that this only works if you actually have a member with the account number 51000 and 52000 in your Expense dimension (see comments).
An entirely different approach, would be to perform this logic in your ETL process. For example you could have a table of account-number ranges that map to a particular accounting type (Absorption, Selling & Marketing, etc.). You could then add a new attribute to your Expense-dimension, holding the accounting type for each account, and populate it using dynamic SQL and the aforementioned mapping table.
I don't go near cube scripts but do you not need to create some context via the currentmember function and also return some values for correct evaluation against the inequality operators (e.g.>) via the use of say the membervalue function ?
CREATE MEMBER CURRENTCUBE.[Measures].[Absorption]
AS sum
(
[Expense].[Amount Category].&[OS]
*
Filter(
[Expense].[Account Number].MEMBERS,
[Expense].[Account Number].currentmember.membervalue >= 51000
AND
[Expense].[Account Number].currentmember.membervalue < 52000
)
,
[Measures].[Amount - Expense]
),
VISIBLE = 1 , ASSOCIATED_MEASURE_GROUP = 'Expense';
EDIT
Dan has used the range operator :. Please make sure your hierarchy is ordered correctly and that the members you use with this operator actually exist. If they do not exist then they will be evaluated as null:
Against the AdvWks cube:
SELECT
{} ON 0
,{
[Date].[Calendar].[Month].&[2008]&[4]
:
[Date].[Calendar].[Month].&[2009]&[2]
} ON 1
FROM [Adventure Works];
Returns the following:
If the left hand member does not exist in the cube then it is evaluated as null and therefore open ended on that side:
SELECT
{} ON 0
,{
[Date].[Calendar].[Month].&[2008]&[4]
:
[Date].[Calendar].[Month].&[1066]&[2] //<<year 1066 obviously not in our cube
} ON 1
FROM [Adventure Works];
Returns:

MDX Error while creating Calculated Measure

I am trying to create a calculated measure that finds the difference between two measures by using the following mdx query
WITH MEMBER [Measures].[Available]
AS ([Measures].[Capacity days] ,[Project].[Projects by Name].[All],[Project].[Projects by Code].[All])
- ([Measures].[Worked Days] ,EXCEPT([Project].[Projects by Name].[Project].MEMBERS,
[Project].[Projects by Name].[Project].&[1214]),[Version].[Version].[Combined],[Charge].[Charge].[All])
In case of second measure Worked Days I want to access it with respect to all projects except one ,so am using EXCEPT function which results in the following error
" The function expects a string or numeric expression for the argument. A tuple set expression was used"
Is there any other way to perform this operation?
The query is mixing tuples with sets. Perhaps you can check this gentle introduction of MDX for main concepts and notations.
The second tuple is using a set (the result of EXCEPT) as its second member which is not possible. You could use the aggregate function as following to compute the [Worked Days] over the members of this set instead :
AS ( [Measures].[Capacity days], ... )
- Aggregate(
Except (
[Project].[Projects by Name].[Project].MEMBERS,
[Project].[Projects by Name].[Project].&[1214]
),
( [Measures].[Worked Days], ... )
)

Filtering dimensions in MDX inside a SUM

I am new to MDX expressions and I am trying to create one that sums the value of a given measure filtered by dimensions.
In my database I have several different dimensions that have the same name: "Answer". To sum them up, I have created the query below:
WITH MEMBER Measures.Total as SUM ({[Activity].[Activity].&[14], [Activity][Activity].&[22]},
[Measures].[Activity time])
SELECT NON EMPTY [Measures].[Total] on COLUMNS from [My Analytics]
This query works, however I had to use the "&[14]" and "&[22]" statments that correspond to two different "Answer" dimensions.
Since I have more than two dimensions with the same name, is there a way to rewrite the query above in a way that I would select all these dimensions without having to add their unique ID? For example, I would re-write the query as something like this:
WITH MEMBER Measures.Total as SUM ({[Activity].[Activity].&["Answer"]},
[Measures].[Activity time])
SELECT NON EMPTY [Measures].[Total] on COLUMNS from [My Analytics]
Is this possible?
Thanks!
You can use the Filter function as following:
with
set [my-answers] as
Filter( [Activity].[Activity].members,
[Activity].[Activity].currentMember.name = 'Answer'
)
member [Measures].[Total] as Sum( [my-answers] )
...

How to get current row value in a WITH MEMBER calculation MDX?

I would like to calculate a Measure based on the current row.
Problem is I can't find a way to get the current row in a WITH MEMBER part.
WITH MEMBER [Measures].[Test] AS AVG(
NonEmptyCrossJoin(
FILTER(DESCENDANTS([Exigences].[ENVGR], [Levier], SELF),
[Exigences].CurrentMember.Name = 'Chemicals'),
DESCENDANTS([Organization].[Valeo].[Powertrain Systems], [entity], SELF)),
[Measures].[ProgressLevel])
SELECT {[Measures].[ProgressLevel], [Measures].[Test]} ON COLUMNS,
DESCENDANTS([Exigences].[ENVGR].[ENVGR-01.001], [Levier], SELF) ON
ROWS FROM [Exigences]
Chemicals is currently hard coded. That is for the example.
I would like in place of 'Chemicals' to have the current rows value.
So let's say those are the values rows will return 'Chemicals', 'Pharmacy', 'Test', I would like the [Measures].[Test] calculation to change.
Can MDX do that ? If so how can I get the current value.
I tried [Levier].CurrentMember.Name but I think it's conflicting with the [Exigences].CurrentMember.Name.
Any one has an idea ?
Thank you,
This has been taking a bit of effort but that's the advantage to have a nice gold badge. We're using the MDX Generate function and named sets (myCellSet & 2d example in link) :
Not sure this is going to work for your provider but you can try this one :
WITH MEMBER [Measures].[Test] AS AVG(
NonEmptyCrossJoin(
Generate( {[Exigences].CurrentMember} as MyCellSet,
FILTER(DESCENDANTS([Exigences].[ENVGR], [Levier], SELF),
[Exigences].CurrentMember.Name = MyCellSet.CurrentMember.Name)
)
,
DESCENDANTS([Organization].[Valeo].[Powertrain Systems], [entity], SELF)),
[Measures].[ProgressLevel])