SSAS Calculated Member for measures that have the same Dimension - ssas

I am trying to create a calculated measure that subtracts measures that are in different groups, but only if they have the same dimension member whatever that may be. (edit - essentially exclude UnknownMember numbers in the subtraction)
I have tried using Scope:
CREATE MEMBER CURRENTCUBE.[Measures].[CalcField] as NULL;
SCOPE([Dimension1].[DimensionField1].MEMBERS);
[Measures].[CalcField] = [Measures].[a] - [Measures].[b];
END SCOPE;
I have also tried using a Tuple without success:
CREATE MEMBER CURRENTCUBE.[Measures].[CalcField]
AS ([Measures].[a] - [Measures].[b], [Dimension1].[DimensionField1]);
But I think there is something fundamental that I am missing
Edit
col a b dimension
1. 9 0 x
2. 0 2 x
3. 1 5 null
If you aggregate those rows I want the answer 7 not 5
Using a simple CASE WHEN works if the dimensions in use, but otherwise it blindly subtracts everything again
CASE
WHEN [Dimension1].[DimensionField1] IS [Dimension1].[DimensionField1].UnknownMember THEN 0
ELSE [Measures].[a] - [Measures].[b]
END
Using Aggregate works at the high level, but then when I use the Dimension I get no per member results
Aggregate(
EXCEPT(
[Dimension1].[DimensionField1].Members, {[Dimension1].[DimensionField1].UnknownMember, [Dimension1].[DimensionField1].[All]}
),[Measures].[a])
-
Aggregate(
EXCEPT(
[Dimension1].[DimensionField1].Members, {[Dimension1].[DimensionField1].UnknownMember, [Dimension1].[DimensionField1].[All]}
),[Measures].[b])
Workaround Solution
I am sorry if I was not clear on my problem, but I have ended up solving this problem by putting the data I need in at the ETL stage rather than calculating it in the Cube

Did you try either Summing or Aggregating your second snippet?
CREATE MEMBER CURRENTCUBE.[Measures].[CalcField]
AS
Sum(
[Measures].[a] - [Measures].[b],
[Dimension1].[DimensionField1]
);
CREATE MEMBER CURRENTCUBE.[Measures].[CalcField]
AS
Aggregate(
[Measures].[a] - [Measures].[b],
[Dimension1].[DimensionField1]
);

With Member [Measures].[CalcField] as [Measures].[a] - [Measures].[b]
Select [Measures].[CalcField]
on columns,
[Dimension1].[DimensionField1].MEMBERS
on rows
from [cube]

Related

Total Sum of Calculated member is wrong

I have there tables:
Artikal (eng. Item)
Grupa (eng. Group)
Potrosnja (eng. Consumption)
Potrosnja is my Measure table and Artikal is Dimension. Grupa contains also a parent-child relationship between groups. For now, is only one level. Inside the Artikal dimension I created
Hierarchy: Grupa.ParentId, Grupa.GrupaId, Artikal.Id. Name of Hierarhcy is PGA.
This shows well in Power BI. I also create some calculated Members: Cijena LY and Vrijednost LY.
I need to create a calculated member and the formula goes
(Cijena - Cijena LY)* Kolicina
First I tried to create like a calculated member but I saw that my total was also creating like the formula of totals of formulas. I want that my total for this member is SUM of calculated member column
I trying to do this with SCOPE, but I don't get the right result. Here is my script:
CREATE MEMBER CURRENTCUBE.[Measures].[Suma razlike] AS null,
VISIBLE = 1;
SCOPE([Measures].[Suma razlike],[Artikal].[PGA].members);
This =sum(
Descendants([Artikal].[PGA].CurrentMember,,LEAVES),
(([Measures].[Cijena]-[Measures].[Cijena LY])*[Measures].[Kolicina]));
END SCOPE;
Can somebody tell me what I am doing wrong? I creating this in Analysis services by Microsoft.
The solution was provided on the different blog by Alexei Stoyanovsky:
The problem was that was created hidden subselect. I needed to create a Dynamic set of Artikal. Here is solution:
CREATE DYNAMIC SET CURRENTCUBE.[MyTestSet] AS [Artikal].[Id].[Id].members;
SCOPE([Measures].[Suma razlike], [Artikal].[Id].members); --Includes All +
other members
This = case when [Artikal].[Id].currentmember.level.ordinal>0 then
([Measures].[Cijena]-[Measures].[Cijena LY])*[Measures].[Kolicina]
else
sum(existing [MyTestSet], ([Measures].[Cijena]-[Measures].[Cijena LY])*
[Measures].[Kolicina]) --All member is not included
end;
FORMAT_STRING([Measures].[Vrijednost - CPI])='Percent';
FORMAT_STRING([Measures].[Postotak razlike])='Percent';
FORMAT_STRING([Measures].[Razlika artikal - CPI])='Percent';
END SCOPE;

Complex Filter on SSAS calculated Member

I Tried to create a calculated measure inn my SSAS cube with complex filters as the following:
([Measures].[Amount],[Scenarios].[Scenario Key].&[1],[AccountType],[AccountType].[Account Type].&[Bank],[AccountType].[Account Type].&[Cash],[AccountType].[Account Type].&[NotesReceivable],[JE Type].[JE Type].&[CI],[JE Type].[JE Type].&[NR])
I want to Get the summation of amount value which has:
Scenario Key = 1
Account Type IN ("Bank","Cash","NotesReceivable")
JE Type IN ("CI","NR")
But i Get this measure as Null So can any one can help to solve this?
It's not working because you are doing an intersection of the same dimension hierarchy:
[AccountType].[Account Type].&[Bank],[AccountType].[Account Type].&[Cash]
means in MDX: Account Type = Bank AND Account Type = Cash at the same time.
Just use set of members and SUM function.
Try this one:
SUM(
{[AccountType].[Account Type].&[Bank]
,[AccountType].[Account Type].&[Cash]
,[AccountType].[Account Type].&[NotesReceivable]}
*
{[JE Type].[JE Type].&[CI]
,[JE Type].[JE Type].&[NR]}
,([Scenarios].[Scenario Key].&[1],[Measures].[Amount]))
Explanation:
SUM - aggregate function
Dimension1 filter * Dimension2 filter - gave all combinations
(Dimension3,measure) - filters out single-selected dimensions

MDX - Add Calculated Percent Measure into a Range

i didn't found any solution for my problem. Or maybe i dont know the right keywords.
Problem:
Cube contains a calculated member measure:
CREATE MEMBER CURRENTCUBE.[Measures].[Percentage] as
iif([Measures].[Performance GB]=0, null,
[Measures].[Performance GB]/[Measures].[Package GB]),
FORMAT_STRING = "0#.#0 %;-#.#0 %",
VISIBLE = 1;
Now i need another attribute to group the percent values into a range.
My first idea was this member with 4 additional measures. For example:
create MEMBER CURRENTCUBE.[Measures].[0-25%] AS
IIF(
[Measures].[Percentage]>0 AND [Measures].[Percentage]<26
,1
,NULL),VISIBLE = 1;
It works if i show the values on the contract level.
But a deeper watch shows wrong values:
CubeSelection
Whats my error?
Can you try changing 26 to 0.26?
create MEMBER CURRENTCUBE.[Measures].[0-25%] AS
IIF(
[Measures].[Percentage]>0 AND [Measures].[Percentage]<0.26
,1
,NULL),VISIBLE = 1;
My first idea was the wrong way.
The solution is a calucalted field to generate the DimensionKey
when (PerformanceGB/ServiceGB)*100 between 0 and 11 then 1
when (PerformanceGB/ServiceGB)*100 between 11 and 21 then 2
....
And then i could use the PercentRange as a Dimension

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:

How to filter a measure based on another measure

I have a dimension table called DimUser that has 1 row per user. I have a measure based on this dimension called "USER COUNT" which is count of rows of the DimUser table. I also have a calculated measure called "ACTIVE DAYS" which returns no of days a user is active.
Now, I want to create another calculated measure based on this 2 measures, where I count only users who are active more than 5 days. I have total 5 users in my user table and 2 users in my fact table who are active more than 5 days. My MDX expression should return 2.
This is what I wrote
FILTER([Measures].[USER COUNT], [Measures].[ACTIVE DAYS] > 5)
But this gives me 5 as the answer instead of 2. What am I doing wrong?
Next I tried this, but this fails compilation saying two measures in the expression are not allowed
([Measures].[USER COUNT], [Measures].[ACTIVE DAYS] > 5)
Next, I tried creating a new calculated member called [IsActive] that returns true or false if active days > 5 and then use that as filter on the [Measures].[USER COUNT].
How do I go about doing this?
First of all, I don't think it is even possible to filter one measure on another measure, because measures are numeric values, not a set. The concept of filtering applies to a set. So filtering a measure based on another measure is absurd. What can be done though, in terms of MDX, is to create a set of users with the first filter applied(i.e. [Measures].[ACTIVE DAYS] > 5) and then getting a COUNT out of it.
Something like this(NOT TESTED):
WITH SET [ActiveUsersMoreThan5Days] AS
FILTER([User].[UserId].CHILDREN, [Measures].[ACTIVE DAYS] > 5)
//Assuming the User dimension and hierarchy here..
//Fill it in with actual..
MEMBER [Measures].CountActiveUsersMoreThan5Days AS
COUNT(NONEMPTY([ActiveUsersMoreThan5Days], [Measures].[<<Some other measure>>]))
SELECT [Measures].CountActiveUsersMoreThan5Days on 0
//,[Dimension].Hierarchy.CHILDREN ON 1
FROM [Cube]
To avoid using Filter which is iterative and not the best performing function. Also to create a measure that is context aware then the following might help:
WITH
MEMBER [Measures].[CntUsersActive5DaysOrMore] AS
Sum
(
[UserId].[UserId] //<<< or [UserId].[UserId].[UserId]
,IIF
(
[Measures].[ACTIVE DAYS] > 5
,1
,0
)
)
SELECT
[Measures].[CntUsersActive5DaysOrMore] ON 0
FROM [YourCube];