mdx - how to replace null values with '0' in measures members - mdx

In my MDX query I'm using this set of measures in my SELECT statement:
With SET [Selected Measures] AS {
[Measures].[CTR],
[Measures].[Cost],
[Measures].[Clicks]
}
I want in my result to replace the NULL values in '0'.
How to do this?

Try re-defining your measures:
With member [Measures].[Not Null CTR] as Iif( IsEmpty( [Measures].[CTR] ), 0, [Measures].[CTR] )
...
Select { [Measures].[Not Null CTR], ...} on Columns
...
Perhaps changing the measure name for something nicer or renaming the columns back to the original names on the client.
EDIT: If you want to keep the names and the names output by your client are just CTR, etc. (without brackets or the Measures prefix), and you have an extra dimension available somewhere (one that is not used anywhere else in the query), you can define those new members in that extra dimension:
With member [My Other Dim].[CTR] as Iif( IsEmpty( [Measures].[CTR] ), 0, [Measures].[CTR] )
...
Select { [My Other Dim].[CTR], ...} on rows,
...
Definitely not an elegant solution, but it works.

Is it possible to touch upon the cube design? If so you need the open the cube solution, navigate to the "Calculations" tab and add in the below code. Then deploy the changes.
SCOPE([Measures].[CTR]);
IF THIS IS NULL THEN this = 0 END IF;
END SCOPE;
SCOPE([Measures].[Cost]);
IF THIS IS NULL THEN this = 0 END IF;
END SCOPE;
SCOPE([Measures].[Clicks]);
IF THIS IS NULL THEN this = 0 END IF;
END SCOPE;

Based on the first answer, here is an approach that work for the all the measures in the cube :
SCOPE([Measures].MEMBERS);
THIS = IIF(IsEmpty([Measures].CurrentMember) , 0, [Measures].CurrentMember);
END SCOPE;
hope it helps.

Related

What is the return value of Currentmember.Level? (MDX)

is the return value of Currentmember.level an integer or something else?
I get only null values if I try to show me the value.
Here are two pictures about my hierarchy: https://abload.de/img/screenshot_zeite1kns.png
https://abload.de/img/screenshot_zeit_attrio5j17.png
How your MDX query looks like:
Something like this should return level names:
with member measures.currentmemberlevel as [Date].[Calendar].CurrentMember.Level.Name
select measures.currentmemberlevel on 0,
[Date].[Calendar].members on 1
from
[Adventure Works]
If you want level as an integer try
... .currentmember.level_number

Displaying SSAS measure in thousands or millions

I have an Olap cube created using Microsoft SSAS. Inside I have a many-to-many relationship between source transaction currency and required "Reporting" currency. This is all functional, however to display a dynamic currency symbol I am using the "Currency" format string default and passing in a custom LCID based on the currency selected.
The problem with using the "Currency" format is the decimal places and large numbers. I am reporting millions of pounds/dollars and my CFO wants to see these numbers reported in thousands or millions. To control this I have read about using a special format string like #,, but this won't allow the currency symbol to be shown.
I had an idea to have a special dimension which would equate to 1, 1000, 1000000 and then create a calculated measure which divides by this (obviously defaulting to 1 and not aggregatable), but I have lots of measures.
Can anybody else advise on an alternative approach?
I would just set the FORMAT_STRING via a script assignment:
FORMAT_STRING(([Dim-Currency].[Currency Code].&[USD])) = "$#,,";
FORMAT_STRING(([Dim-Currency].[Currency Code].&[Euro])) = "€#,,";
You may use the SCOPE statement here:
Scope(AddCalculatedMembers([Measures].Members));
This = case
when [Measures].CurrentMember >= 1000000
then Cstr(Cint([Measures].CurrentMember / 1000000)) + " millions"
when [Measures].CurrentMember >= 1000
then Cstr(Cint([Measures].CurrentMember / 1000)) + " thousands"
else [Measures].CurrentMember
end;
End Scope;
Where Cint return int value and Cstr helps to join int value to text. I'm not sure if it's not too much. I've never used the "Currency" type, honestly.
I'm with #GregGalloway. In our cube-script it is implemented like this:
Scope
([Dim-Currency].[Currency Code].&[EUR]);
//EUR
FORMAT_STRING(This) = '€ #,##0.00';
End Scope;
Scope
([Dim-Currency].[Currency Code].&[GBP]);
FORMAT_STRING(This) = '£ #,##0.00';
End Scope;
We render via Pyramid front-end.

Mdx Query Show Year Level Data for all years except This Year

SELECT
NON EMPTY
{[Measures].[AMOUNTCUR]} ON 0
,NON EMPTY
{
NULL : [PRX_UE_DATE].[Calender].[Year].&[2015]
,[PRX_UE_DATE].[Calender].[Year].&[2017]
,Descendants
(
[PRX_UE_DATE].[Calender].[Year].&[2016]
,[PRX_UE_DATE].[Calender].[Month]
)
} ON 1
FROM [PRX_SalesDataModel];
I have a query like above. It's working It returns 2016 on month based others years are year based.
Now I have to add more dimensions on this mdx but when i try it to like
SELECT
NON EMPTY
{[Measures].[AMOUNTCUR]} ON 0
,NON EMPTY
{
NULL : [PRX_UE_DATE].[Calender].[Year].&[2015]
,[PRX_UE_DATE].[Calender].[Year].&[2017]
,
Descendants
(
[PRX_UE_DATE].[Calender].[Year].&[2016]
,[PRX_UE_DATE].[Calender].[Month]
)
*
[PRX UE CLIENT].[SEGMENTID].ALLMEMBERS
} ON 1
FROM [PRX_SalesDataModel];
I get error Members, tuples or sets must use the same hierarchies in the function.
You just need to keep all the date dimension stuff in set braces {...}:
SELECT
NON EMPTY
{[Measures].[AMOUNTCUR]} ON 0
,NON EMPTY
{
NULL : [PRX_UE_DATE].[Calender].[Year].&[2015]
,[PRX_UE_DATE].[Calender].[Year].&[2017]
,
Descendants
(
[PRX_UE_DATE].[Calender].[Year].&[2016]
,[PRX_UE_DATE].[Calender].[Month]
)
}
* [PRX UE CLIENT].[SEGMENTID].ALLMEMBERS
ON 1
FROM [PRX_SalesDataModel];
You could even make it maybe more readable by moving the date stuff into a named set via a WITH clause:
WITH SET [DatesSet] AS
{
NULL : [PRX_UE_DATE].[Calender].[Year].&[2015]
,[PRX_UE_DATE].[Calender].[Year].&[2017]
,
Descendants
(
[PRX_UE_DATE].[Calender].[Year].&[2016]
,[PRX_UE_DATE].[Calender].[Month]
)
}
SELECT
NON EMPTY
{[Measures].[AMOUNTCUR]} ON 0
,NON EMPTY
[DatesSet]
* [PRX UE CLIENT].[SEGMENTID].ALLMEMBERS
ON 1
FROM [PRX_SalesDataModel];
You've got your answer from #whytheq on why the error cropped up. There is just one part which I felt is not handled yet. You are building the set of years by hand. Instead of that, it can be made dynamic like below -
with set AllYearsExceptCurrent as
filter(
[PRX_UE_DATE].[Calender].[Year].members as yr,
yr.current.item(0).member_value <> Format(Now(), "yyyy")
)

IF Statement in a calculated field (SSAS Tabular)

I'm in the process of creating a tabular model cube in SSAS and I've become a bit stuck on some of my measures for the calculated columns
I have already converted this case statement to an IF in SSAS
case when PROPERTY_CHARGE.PCH_CURRENT_IND='Y' then PROPERTY_CHARGE.PCH_AMT else 0 end
is now
=If ([PCH_CURRENT_IND]="Y", [PCH_AMT],0)
I'm now struggling to convert this one:
sum(case when PROPERTY_CHARGE.PCH_CURRENT_IND='N' and PROPERTY_CHARGE.PCH_END_DATE is null then PROPERTY_CHARGE.PCH_AMT else 0 end
I've tried various arrangements but no matter what i'm getting errors either related to is null or AND not being available in this context or other errors advising I have too many arguments.
Can anyone assist please?
IN tabular is very different the logic, you can create a measure like this :
MeasureName:=CALCULATE(sum([PCH_AMT]),FILTER(PROPERTY_CHARGE,[PCH_CURRENT_IND]="N"&&[PCH_END_DATE]=BLANK()))
ANd give you the same result of case
use:
=If ([PCH_CURRENT_IND]="Y", [PCH_AMT],BLANK())
and then :
MeasureName:
=CALCULATE(sum([PCH_AMT]),FILTER(PROPERTY_CHARGE,[PCH_CURRENT_IND]="N"&&[PCH_END_DATE]=BLANK()))
that is the same as the case
This solution will be a little more performant than the previous posts and a little easier to read, use this for a Measure:
Strruggling To Convert measure:=
CALCULATE (
SUM ( 'PROPERTY_CHARGE'[PCH_AMT] ),
FILTER (
ALL ( 'PROPERTY_CHARGE'[PCH_CURRENT_IND], 'PROPERTY_CHARGE'[PCH_END_DATE] ),
AND (
'PROPERTY_CHARGE'[PCH_CURRENT_IND] = "N",
ISBLANK ( 'PROPERTY_CHARGE'[PCH_END_DATE] )
)
)
)
Struggling To Convert Calculate column :=
SWITCH (
TRUE (),
AND (
'PROPERTY_CHARGE'[PCH_CURRENT_IND] = "N",
ISBLANK ( 'PROPERTY_CHARGE'[PCH_END_DATE] )
), SUM ( 'PROPERTY_CHARGE'[PCH_AMT] )
)

MDX Scope for all attributes of a dimension

I have a dimension X with 10 attributes 1..10. In order to make a custom calculation for measure Y within a scope I can write this statement:
SCOPE([X].[1].CHILDREN, [Measures].[Y]);
THIS = 1+1;
END SCOPE;
This will make sure that when dimension attribute 1 is selected together with Y then the result will be 2.
Is there any easy way of writing this to make sure it works for all attributes within dimension X instead of using a nested scope and explicitly defining it for all attributes?
Something like SCOPE([X].[*]) or similar?
Create one more calculated member like this:
CREATE MEMBER DimSelected AS
IIF(
[X].[1].CURRENTMEMBER IS [X].[1].[All]
AND
[X].[2].CURRENTMEMBER IS [X].[2].[All]
AND
[X].[3].CURRENTMEMBER IS [X].[3].[All]
AND
[X].[4].CURRENTMEMBER IS [X].[4].[All]
AND
[X].[5].CURRENTMEMBER IS [X].[5].[All]
AND
[X].[6].CURRENTMEMBER IS [X].[6].[All]
AND
[X].[7].CURRENTMEMBER IS [X].[7].[All]
AND
[X].[8].CURRENTMEMBER IS [X].[8].[All]
AND
[X].[9].CURRENTMEMBER IS [X].[9].[All]
AND
[X].[10].CURRENTMEMBER IS [X].[10].[All],
NULL,
1)
And modify your scope logic to below:
SCOPE([Measures].[Y]);
IF Measures.DimSelected = 1 THEN This = 1+1 END IF;
END SCOPE;
Alternatively if you just plan to ever select the dim on some given axis, below might work:
CREATE MEMBER MembersSelected AS
GENERATE(AXIS(1) AS a, a.current.item(0).unique_name)
CREATE member HasX as
IIF(instr(1,MembersSelected,"[X].") <> 0, "Yes", NULL)
Then modify your scope logic to below:
SCOPE([Measures].[Y]);
IF Measures.HasX = "Yes" THEN This = 1+1 END IF;
END SCOPE;