I'm trying to design a calculation in a cube's MDX calculation so that when a specific value of a dimension is used, the behavior/values returned by the measure is change to something else, based on other values from the same dimension attribute.
here's my code sample :
CREATE SET CURRENTCUBE.[NonBreakDownIndicators]
AS {([Indicator Label].[Indicator].MEMBERS - [Indicator Label].[Indicator].&[Indicator Daily Diff])}
;
SCOPE([Measures].[Value Unit], [Indicator Label].[Indicator].&[Indicator Daily Diff]);
//SCOPE([NonBreakDownIndicators]);
THIS = ([Indicator Label].[Indicator].&[SensiDiv],[Measures].[Daily Diff Unit]);
//THIS = [Measures].[Daily Diff Unit];
//END SCOPE;
END SCOPE;
What we can see here is that I want to create a tuple with some dimension 'Indicator' values, except one. I have 3000+ values in this dimension attribute.
Next, when a user select, among others, the attribute Indicator, and among the selected values, one is 'Indicator Daily Diff', I want to change the values returned by the measure 'Value Unit', to instead get the values from 'Daily Diff Unit'.
This last measure is tested and working.
So far I've managed to get a result with the currently uncommented code. But as you can see this will only work for 1 value of the 'Indicator' dimension, when I would need to make it work for thousands of them.
I've tried to use a sub scope as you can see in the commented code, but I get this exception :
An arbitrary shape of sets is not allowed in the current context.
I've also tried to use the Tuple set [NonBreakDownIndicators] in the THIS statement like this :
SCOPE([Measures].[Value Unit], [Indicator Label].[Indicator].&[Indicator Daily Diff]);
THIS = ([NonBreakDownIndicators],[Measures].[Daily Diff Unit]);
END SCOPE;
But then I would end up with a 'null' value in my cube (not empty or not showing, a cell is filled with null).
I'm not SSAS expert and I'm mostly doing stuff hoping to get some keywords to look up, but so far internet blogs have had little infos on my topic, and I can find anyone around me with enough knowledge on this technology.
Does anyone have an idea about how I could achieve this without having to specify every single Indicator the MDX?
PS: I can't use a measure to solve this. My client explicitely asked for this 'Daily Diff Unit' to be shown as indicator, in order to have only one measure, and as many indicator as they need.
Edit
I did this change and indeed it resolve the 'arbitrary shape of sets' error. But now I don't get any figure back when querying.
I can see other figures on other 'Indicators', but no cell is returned for the [Indicator Daily Diff] indicator. I'm using this right now :
CREATE SET CURRENTCUBE.[NonBreakDownIndicators]
AS {([Indicator Label].[Indicator].[Indicator].MEMBERS - [Indicator Label].[Indicator].&[Indicator Daily Diff])}
;
SCOPE([Measures].[Value Unit], [Indicator Label].[Indicator].&[Indicator Daily Diff]);
SCOPE([NonBreakDownIndicators]);
THIS = ([NonBreakDownIndicators],[Measures].[Daily Diff Unit]);
END SCOPE;
END SCOPE;
Try changing the set to the following to see if that avoids the arbitrary shape error:
CREATE SET CURRENTCUBE.[NonBreakDownIndicators]
AS {([Indicator Label].[Indicator].[Indicator].MEMBERS - [Indicator Label].[Indicator].&[Indicator Daily Diff])}
;
You can have random members of a single level and scope on that set. But you can't have random members of multiple levels and scope on that set. The change above removed the All member from the set which I believe should ensure all members in the set are on the same level.
Then I would try:
SCOPE([Measures].[Value Unit], [Indicator Label].[Indicator].&[Indicator Daily Diff]);
THIS = ([Measures].[Daily Diff Unit]);
END SCOPE;
Or possibly:
SCOPE([Measures].[Value Unit], [Indicator Label].[Indicator].&[Indicator Daily Diff]);
THIS = SUM([NonBreakDownIndicators],[Measures].[Daily Diff Unit]);
END SCOPE;
(Posted on behalf of the question author).
Following the advice of Greg, here is the MDX code that answer my need perfectly:
CREATE DYNAMIC SET CURRENTCUBE.[NonBreakDownIndicators]
AS {(
[Indicator Label].[Indicator].[Indicator].MEMBERS
- [Indicator Label].[Indicator].&[Indicator Daily Diff]
- [Indicator Label].[Indicator].&[Params Variation]
- [Indicator Label].[Indicator].&[Secondary Variation]
- [Indicator Label].[Indicator].&[Primary Variation]
- [Indicator Label].[Indicator].&[Expired Variation]
)};
SCOPE([Measures].[Value Unit], [Indicator Label].[Indicator].&[Indicator Daily Diff]);
THIS = SUM([NonBreakDownIndicators],[Measures].[Daily Diff Unit]);
END SCOPE;
SCOPE([Measures].[Value k¤], [Indicator Label].[Indicator].&[Indicator Daily Diff]);
THIS = SUM([NonBreakDownIndicators],[Measures].[Daily Diff k¤]);
END SCOPE;
It even allowed me to decline the behavior for other measure groups (simple values, counter valorised values,...). It supports the currently used Indicators and filter out the others.
Related
I have a fact table say WhsFactJob where we have CreatedTimeKey and InProgressTimeKey and I have a measure where Job Count.
I am trying to create a Calculated measure which will fetch me the job count whose CreatedTimeKey falls between 1(1:00 AM) and 2(2:00 AM) and InProgressTimeKey also falls with the same 1(1:00 AM) and 2(2:00 AM).
I tried to use SUM and Except, But it errors out saying Except has to use the same hierarchy.( CreatedTimeKey and InprogressTime Key are two seperate dimensions.
Any suggestions would help.
Here is the MDX example I am trying out.
WITH
MEMBER [Measures].[Sum] AS
SUM(
EXCEPT(
{[Created Time].[Hour].&[0]:[Created Time].[Hour].&[14]},
{[In Progress Time].[Hour].&[0]:[In Progress Time].[Hour].&[14]}
)
,[Measures].[Job Count]
)
SELECT
[Measures].[Sum] ON 0
FROM [Cube]
I'm not clear why you're using EXCEPT. How about this:
SUM
(
CROSSJOIN(
{[Created Time].[Hour].&[0]:[Created Time].[Hour].&[14]},
{[In Progress Time].[Hour].&[0]:[In Progress Time].[Hour].&[14]}
)
,[Measures].[Job Count]
)
I think you can get rid of the exception by cross-joining each set to members from the other set: not sure if the result of the query will be useful though - currently I'm unable to test the following:
The dimensionality of the two sets of tuples within the EXCEPT function should now be the same:
WITH
MEMBER [Measures].[Sum] AS
SUM(
EXCEPT(
{[Created Time].[Hour].&[0]:[Created Time].[Hour].&[14]}
*[In Progress Time].[Hour].[Hour].MEMBERS
, [Created Time].[Hour].[Hour].MEMBERS
*{[In Progress Time].[Hour].&[0]:[In Progress Time].[Hour].&[14]}
)
,[Measures].[Job Count]
)
SELECT
[Measures].[Sum] ON 0
FROM [Cube];
I am interested in getting some help regarding my mdx queries.
I wanted to have a field that is multi-currency. I was able to allow the user to aggregate if the currency was same.
SCOPE [Measures].[Base Gross Amount];
This =
iif([Measures].[Measures].[MaximumCurrencyID] = [Measures].[Measures].[MinimumCurrency ID], [Measures].[Base Gross Amount], "Multiple Currencies");
End Scope;
However, now the user also wants to display the appropriate currency format. So when I added another scope statement to format the measure, this works for the leaves but not for the All member, it just adds the word "All" to the formatting, any thoughts how can I get the descendants?
SCOPE ([Company Organization].[Order Company ID].members, [Measures].[Base Gross Amount] );
Format_String(this) = [Company Organization].[Symbol].currentmember.Member_Value + "#,#.##";
End Scope;
The problem must be originating here: [Company Organization].[Symbol].
Can you set the [Symbol] hierarchy so it has no All member: in a similar way that the measures hierarchy has no All member.
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 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.
We have a two-cube solution built in AS 2008 that works like this: an Industry cube that contains Widget data for all clients, and a Client cube that contains Widget data & shares several (but not all) dimensions with the Industry. The Industry cube contains everybody, including the calling client, so when the Client is pulling an Industry measure, we want the results to include everybody else. Clients are represented in the Industry cube with a "clients" dimension that just has two members: the key & the client name. The industry cube's count measure is called [I Widget Count] & the same measure in the client cube is [Widget Count].
An MDX expression like this works great from the query editor:
WITH SET [Industry] AS Except( [Cube Clients].[Client].[All].Children
, [Cube Clients].[Client].[Client 05] )
MEMBER [Measures].[Industry Widget Count] AS sum( [Industry], [I Widget Count] )
SELECT ({ [Widget Count]
, [Industry Widget Count]
, [I Widget Count] }) on 0
FROM [Client 05 Cube]
Everything seems fine, the counts for client & industry are perfect. Adding shared or non-shared dimensions to axis 1 works also, & everything seems great.
As soon as I add the set to the cube itself, the sum functions stop giving correct answers. So, in the calculated measures screen I've added:
CREATE DYNAMIC SET CURRENTCUBE.[Industry]
AS Except( [Cube Clients].[Client].[All].Children
, [Cube Clients].[Client].[Client 05] ) ;
CREATE MEMBER CURRENTCUBE.[Measures].[Industry Widget Count]
AS sum( [Industry], [I Widget Count] ),
VISIBLE = 1 ;
When browsing this measure in the cube, the count is completely wrong. The correct number (with no dimension constraints) is around 10,000,000 & the browser shows 30. I've tried looking through a trace window to see if I can read the code that the cube is using to generate the dynamic sum, but it is not visible.
Anyone have a clue why this is happening?