I want to make some Calculated Measures in my cube that conditionally use a value from the measure table, based on a dimension attribute value.
For example: where Document Status in the Document dimension is CP, use the Committed Value measure. This is what I have for that:
CREATE MEMBER CURRENTCUBE.[Measures].CalcCommittedValue
AS ([Document].[Document Status].&[CP], [Measures].[Committed Value]),
FORMAT_STRING = "$#,##0;-$#,##0",
VISIBLE = 1 , ASSOCIATED_MEASURE_GROUP = 'Document Total' ;
And it looks like it works, until I start browsing the cube and put Document Status and CalcCommittedValue into the Browser. All the options for Document Status display the same CalcCommittedValue.
Thanks for your help!
To do this correctly, try using the SCOPE() statement...for example
CREATE MEMBER CURRENTCUBE.[Measures].[CalcCommittedValue]
AS
SCOPE([Document].[Document Status].[&CP]);
THIS = [Measures].[Committed Value];
END SCOPE;
The Scope statement will cause the value to be calculated whenever the Document Status of [CP] is present, and not otherwise. Very powerful statement, and should get you want you need.
Related
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;
I am trying to replicate the following sql statement into MDX so that I can create a calculated member in the cube using the base loaded members instead of having to calculate it outside the cube in the table and then loading it
SUM(CASE WHEN ((A.SALES_TYPE_CD = 1) AND (A.REG_SALES=0))
THEN A.WIN_SALES
ELSE 0
END) AS Z_SALES
I am currently loading SALES_TYPE_CD as a dimension and REG_SALES and WIN_SALES as measures.
I also have a few other dimensions in the cube but for simplicity, lets just say I have 2 other dimensions, LOCATION and ITEM
The dimension has LOCATION has 3 levels, "Region"->"District"->"Store", ordered from top to bottom level.
The dimension has ITEM has 3 levels, "CLASS"->"SUBCLASS"->"SKU", ordered from top to bottom level.
The dimension has SALES TYPE has 2 levels, "SALES_TYPE_GROUP"->"SALES_TYPE_CD", ordered from top to bottom level.
I know that I cannot create a simple calculated member in the cube which crossjoins the "SALES_TYPE" dimension with another dimension to get the answer I want.
I would think that it would be a more complicated MDX statement something like :
CREATE MEMBER CURRENTCUBE.[Measures].[Z_Sales]
AS 'sum(filter(crossjoin(leaves(), [Sales Type].[Sales Type].
[Sales_Type_CD].&[1]), [Measures].[REG_SALES]=0),[Measures].
[WIN_SALES])',
FORMAT_STRING = '#,#',
VISIBLE = 1 ;
But this does not seem to return the desired result.
What would be the proper MDX code to generate the desired result?
I did a bunch of testing with the data and I now know that there is no way I can get the right answer by using MDX alone in this scenario. Like "Greg" and "Tab" suggested, the only way would be to have reg sales as a dimension. Since this is a measure, that is out of the question because of the large number of possibilities for the value which has a data type of decimal (18,2)
Thanks for taking the time to answer the question.
A measure 'X' gets its value from different fact tables.Lets consider Time (Fiscal Week, Month)dimension and Channel dimension. For different combination of attributes in these two dimensions X will get its value from different tables as follows:
Week + Channel - gets from table FactTrafficByWeekChannel
Week - gets from table FactTrafficByWeek
Month + Channel - gets from table FactTrafficByMonthChannel
Month - gets from table FactTrafficByMonth
To achieve this I added these fact to cube and created a calculated measure and scope scripts to overwrite the scope. Following is the scope script statement:`
CALCULATE;
CREATE MEMBER CURRENTCUBE.[Measures].[Y]
AS (0),
FORMAT_STRING = "Standard",
VISIBLE = 1;
Scope
([Measures].[Y],[Dim Time].[Fiscal Week].[Fiscal Week].Members
) ;
This = [Measures].[X - Vw Fact Total Weekly Traffic];
End Scope ;
Scope
([Measures].[Y],[Dim Time].[Fiscal Week].[Fiscal Week].Members,
[Dim Campaign].[Channel].[Channel].Members
) ;
This = [Measures].[X - Vw Fact Total Weekly Traffic By Channel];
End Scope ;
Scope
([Measures].[Y],[Dim Time].[Fiscal Month].[Fiscal Month].Members
) ;
This = [Measures].[X - Vw Fact Monthly Traffic];
End Scope ;
Scope
([Measures].[Y],[Dim Time].[Fiscal Month].[Fiscal Month].Members,
[Dim Channel].[Channel].[Channel].Members
) ;
This = [Measures].[X - Vw Fact Monthly Traffic By Channel];
End Scope ;
`
Above code works fine when corresponding dimension attributes are dragged in browsing pane but do not work when added to filter pane.
Fiscal Week dimension dragged to browsing pane this works. But
Fiscal Week dimension dragged to filter pane does not work.
This is because attributes added to filter pane are added as sub-cube statements.
Is there a way to achieve this when attributes are dragged to filter pane as well?
Time dimension Attribute relationship (as asked by Greg)
Any help is highly appreciated. Thanks in advance
One way is using dynamic named set as described in this post in the "Using dynamic sets to detect subselects" section.
Add this to the bottom of your existing MDX script:
Create dynamic named set CurrentCube.[SelectedWeeks] as [Dim Time].[Fiscal Week].[Fiscal Week].Members;
Scope
([Measures].[Y],[Dim Time].[Fiscal Month].[All],
[Dim Time].[Fiscal Week].[All],
[Dim Channel].[Channel].[All]
) ;
This = iif(SelectedWeeks.Count<[Dim Time].[Fiscal Week].[Fiscal Week].Members.Count,[Measures].[X - Vw Fact Total Weekly Traffic],0);
End Scope ;
But the problem with that approach is that it is going to get totally out of control checking all the permutations of single select on channel vs multi select on week, etc. And it will likely be slow.
Instead I would recommend removing the Create Member statement for Y from your MDX script and adding a new measure to your "by channel by week" measure group. Call the new physical measure Y and make it a Sum and connect it to a new SQL column that returns 0 on every row. This is just a placeholder measure you will do scoped assignments against. Why physical? When you make a scoped assignment on a physical measure at the channel level for example that assignment aggregates up. (Assignments to calc measures don't aggregate up.) This helps solve the multiselect issue. You assign at the channel level for example and then the All channel number is correct even under multiselect.
That being said, I am not optimistic you will be able to figure out the correct order of scoped assignments so that all 4 of your measures show up where you want with proper multiselect handling. But feel free to try.
One tip is to use Freeze([Measures].[Y], [Dim Time].[Fiscal Month].[All]) after one scoped assignment to months if you are happy with that portion of the cube but find subsequent scoped assignments are changing parts you were happy with.
If you need further help include a screenshot of the Attribute Relationships tab for Dim Time.
I have a question related to creating a (more efficient) custom Distinct Count Measure using MDX.
Background
My cube has several long many to many relationship chains between Facts and Dimensions and it is important for me to be able to track which members in certain Dimensions do and do not relate to other Dimensions. As such, I have created a "Not Related" record in each of my dimension tables and set those records' ID values to -1. Then in my intermediate mapping fact tables I use the -1 ID to connect to these "Not Related" records.
The issue arises when I try to run a normal out-of-the-box distinct count on any field where the -1 members are present. In the case that a -1 member exists, the distinct count measure will return a result of 1 more than the true answer.
To solve this issue I have written the following MDX:
CREATE MEMBER CURRENTCUBE.[Measures].[Provider DCount]
AS
//Oddly enough MDX seems to require that the PID (Provider ID) field be different from both the linking field and the user sliceable field.
SUM( [Providers].[PID Used For MDX].Children ,
//Don't count the 'No Related Record' item.
IIF( NOT([Providers].[PID Used For MDX].CURRENTMEMBER IS [Providers].[PID Used For MDX].&[-1])
//For some reason this seems to be necessary to calculate the Unknown Member correctly.
//The "Regular Provider DCount Measure" below is the out-of-the-box, non-MDX measure built off the same field, and is not shown in the final output.
AND [Measures].[Regular Provider DCount Measure] > 0 , 1 , NULL )
),
VISIBLE = 1 , DISPLAY_FOLDER = 'Distinct Count Measures' ;
The Issue
This MDX works and always shows the correct answer (yeah!), but it is EXTREMELY slow when users start pulling Pivot Tables with more than a few hundred cells that use this measure. For less than 100 cells, the results are nearly instantaneously. For a few thousand cells (which is not uncommon at all), the results could take up to an hour to resolve (uggghhh!).
Can anyone help show me how to write a more efficient MDX formula to accomplish this task? Your help would be GREATLY appreciated!!
Jon Oakdale
jonoakdale#hotmail.com
Jon
You can use predefined scope to nullify all unnecessary (-1) members and than create your measure.
SCOPE ([Providers].[PID Used For MDX].&[-1]
,[Measures].[Regular Provider DCount Measure]);
THIS = NULL;
END SCOPE;
CREATE MEMBER CURRENTCUBE.[Measures].[Provider DCount]
AS
SUM([Providers].[PID Used For MDX].Children
,[Measures].[Regular Provider DCount Measure]),
VISIBLE = 1;
By the way, I used in my tests [Providers].[PID Used For MDX].[All].Children construction since don't know, what is dimension / hierarchy / ALL-level in your case. It seems like [PID Used For MDX] is ALL-level and [Providers] is name of dimension and hierarchy, and HierarchyUniqueName is set to Hide.
How can create generic calculated member which i can reuse in order to calculate the statistical deviation on any logical related dimension(s) and measurement ? I need to be able to select any dimension and measure.
I found related discussion here from which i took stdDev function example.
I've created the calculation, but the result it empty.
CREATE MEMBER CURRENTCUBE.[Measures].calcTest
AS iif(IsEmpty(Axis(0).Item(0)), NULL,
StdDev(Axis(1).Item(0).Item(0).Dimension.Children, Axis(0).Item(0))),
FORMAT_STRING = "#,##0.00;-#,##0.00",
VISIBLE = 1 , ASSOCIATED_MEASURE_GROUP = 'TestMeasure' ;
If you want to use it for all measures, you would put your calcTest member to another hierarchy not used in the query, maybe an utility hierarchy (see below), and then reference the Measures.CurrentMember instead of Axis(0).Item(0).
To get the calculation generalized for all hierarchies except the measures is hard, as somewhere you have to tell the calculation which hierarchy to use. And to do this in the cube before the query is defined cannot be done. Hence, the approach to use the leftmost hierarchy in the rows (Axis(1).Item(0)) taken in your question can be changed to reference something different in the query, but cannot be completely flexible. Of course, an approach could be to define, say, three similar members, one for the first, one for the second, and one for the third hierarchy in the rows.
For the utility hierarchy, you would create a dimension table with just one row and one column. Let's say the data content of this column in the single row is "-standard-"and reference this single member in all fact tables from an additional foreign key. Then you build the dimension into the cube with the references from all measure groups. Lets say the attribute hierarchy is called [Utility].[Utility]. Make the attribute hierarchy non aggregatable, and set the default member to the "-standard-" member. In the calculation script, you can then add members to this utility dimension like
CREATE MEMBER [Utility].[Utility].StdDevRows1 // StdDev for leftmost hierarchy in the rows
AS StdDev(Axis(1).Item(0).Item(0).Dimension.Children, Measures.CurrentMember),
FORMAT_STRING = "#,##0.00;-#,##0.00",
VISIBLE = 1 , ASSOCIATED_MEASURE_GROUP = 'TestMeasure' ;
CREATE MEMBER [Utility].[Utility].StdDevRows2 // StdDev for second hierarchy in the rows
AS StdDev(Axis(1).Item(1).Item(0).Dimension.Children, Measures.CurrentMember),
FORMAT_STRING = "#,##0.00;-#,##0.00",
VISIBLE = 1 , ASSOCIATED_MEASURE_GROUP = 'TestMeasure' ;
CREATE MEMBER [Utility].[Utility].StdDevRows3 // StdDev for third hierarchy in the rows
AS StdDev(Axis(1).Item(2).Item(0).Dimension.Children, Measures.CurrentMember),
FORMAT_STRING = "#,##0.00;-#,##0.00",
VISIBLE = 1 , ASSOCIATED_MEASURE_GROUP = 'TestMeasure' ;
The advantage of a separate utility hierarchy is that you can combine it with all measures, times, etc., as it is not itself a member of these.