Assume that a cube named MyCube has 2 dimensions, and I want to build an MDX SELECT statement without knowing the name of the dimensions but I have a list of elements with one element from each dimension:
SELECT [ELEM X from first dimension] ON 0, [ELEM Y from second dimension] ON 1
FROM [MyCube]
Alternatively is there a function that will return the list of all dimensions and that I can use to built my MDX?
Yes, you can query a dimension without knowing its exact name. You don't even have to know the names of any member, as this example shows. Just be careful in case you are returned a grid of 10000 x 10000 results!
SELECT
{Dimensions(0).Levels(0).members} ON ROWS,
{Dimensions(1).Levels(0).members} ON COLUMNS
FROM [Sales]
It may also be useful to use .members(0) or [Measures].allMembers to specify items where the name is not known.
Related
I am trying to write an MDX Code which has all the members of my cube in the row. However when I specify the row, it mentions that I must ALSO specify Columns. But if I do not set an ON ROW nor an ON Column, my code does not validate.
How do I put all my members in a row, and have a single data column be returned?
In mdx ON COLUMNS is axis 0 and ON ROWS is axis 1. For an mdx statement to be valid it must have at least an axis 0 .... this is one of the rules of the language, no getting around it.
Quite often if I need lots of information in my ON ROWS but the columns needs to be a single column then I will select a dimension I am not using e.g. Language, and then use that selected dimensions ALL member for COLUMNS - just to obey the rule. e.g.
SELECT
[Language].[Language].[All] ON 0, //<<JUST A DUMMY ENTRY BUT MUST BE AN ALL MEMBER OF A DIMENSION
...
...
I have a dimension attribute which has either 1 or 0 and few measures which are count, sum or average.
I don't want to display values of measures which are related to attribute 0.
Ex:
Attribute Name: Is_related
List item : Values: 0 or 1
now, there are few measures like count_of_family which has total value of 1000 in which 700 are related to Is_Related 1 and 300 are related to Is_Related to 0.
I have made Is_Related member value (0) disabled but it is not applied on measure. So, for users they are getting 1000 as by default value and when they are selecting 1 it is filtering it down to 700. I want count_of_family measure to display 700 by default (i.e. omitting data related to 0).
Easiest way to do this is to make (1) the DefaultMember of the Is_related attribute hierarchy in the dimension.
Using Excel Pivot Tables as an example of what the result is in the front end:
Whenever the user creates a new Pivot Table, only the sub-cube (Dimension.Is_related.[1],OtherDimension.All,OtherDimension2.All.... etc) is shown
But if the user drags the Is_related hierarchy onto the pivot table (most appropriately - to the Filters section), only (1) will be selected. They can then select All (or 0), if they want to.
Downside of non-ALL default members is that you have to remember that you set the default member. Any MDX query will only query the subcube (excluding Is_related.[0] in your case), unless you specifically include Is_related.ALL in the WHERE. Which has caught me out in the past, wondering why my results are weird.
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.
I need to create the table of the following structure in MDX (to be used in SSRS report):
For that I have 2 dimensions and one measure:
Option dimension, with option type and option value attributes
Standard dimension, with IsStandard flag
Price measure
In first column I need to show all option type attributes,
in second all value attributes where IsStandard flag is set to [Y],
in third values chosen by user in parameters and
in fourth prices for components selected by user.
Is it possible to do the above in single MDX? Or will I be better off creating 2 distinct queries and creating 2 tables for them?
EDIT: Since my updates won't fit into the comment, I will add some thoughts here.
EXISTS function from answer below does not filter the result set, I don't get standard values but all possible values concatenated. When I issue the following code:
SELECT
[Measures].[Price] ON 0,
NON EMPTY [Option].[Option Type].children
*
[Option].[Option Value].children ON 1
FROM [Cube]
WHERE
(
[Standard].[IsStandard].&[Y],
[Configurations].[Configuration].&[conf1]
)
It returns the default values correctly, but if I use
SELECT
[Measures].[Price] ON 0,
[Option].[Option Type].children
*
EXISTS(
[Option].[Option Value].[Option Value].members
,([Standard].[IsStandard].&[Y],[Configurations].[Configuration].&[conf1])
) ON 1
FROM [Cube]
It does not filter the results.
If you can accept a slightly different order of columns, then this can be done in MDX, using a calculated measure which is actually a string (as you want to see a list of attributes values in column). This avoids having the same attribute twice in the rows:
WITH Member Measures.[Standard Value] AS
Generate(NonEmpty([Option].[Option Type].[Option Type].Members,
{([Standard].[IsStandard].&[Y],
Measures.[Price]
)}
),
[Option].[Option value].CurrentMember.Name,
", "
)
SELECT { Measures.[Standard Value], Measures.[Price] }
ON COLUMNS,
NON EMPTY
[Option].[Option Type].[Option Type].Members
*
{ #chosenValues } // the parameters value should be a comma separated list like "[Option].[Option value].[AMD], [Option].[Option value].[INTEL]"
ON ROWS
FROM [Your Cube]
WHERE [Configurations].[Configuration].&[conf1]
You can adapt the list separator (the last argument of the Generate function) to anything you like.
And in case there is more than one measure group that is related to the dimensions [Option], [Standard], and [Configurations], you should add the name of the measure group to use for determining the relationship as additional last parameter to the Exists, so that you and not the engine determines that. Just use the name of the measure group in either single or double quotes.
Yes it is, dimension will just be ignored. This is assuming you've all in the same schema / cube.
Note, depending on the OLAP Server you're using it's possible you've to change a flag that sends an error if you're using a dimensions that is not defined at Measure Group level.
Is there a way to create a dynamic calculated member based on the dimension selected ON ROWS?
I have the following example with 2 dimensions [Dim1].[Dim1] and [Dim2].[Dim2], with a measure [Measures].[Measure] and a calculated member [Measures].[CalculatedMeasure]:
WITH MEMBER [Measures].[CalculatedMeasure] AS
IIF([Dim1].[Dim1]**.....IS SELECTED ON ROWS.........**,
[Measures].[Measure]
/
([Measures].[Measure], [Dim1].[Dim1].CurrentMember.Parent),
[Measures].[Measure]
/
([Measures].[Measure], [Dim2].[Dim2].CurrentMember.Parent))
SELECT {[Measures].[Measure],[Measures].[CalculatedMeasure]} ON COLUMNS ,
{[Dim2].[Dim2].Members)} ON ROWS
FROM [DataBase]
What I want is that when I select [Dim2].[Dim2] ON ROWS, the calculated member should be the result of
[Measures].[Measure]
/
([Measures].[Measure], [Dim2].[Dim2].CurrentMember.Parent)
ELSE
[Measures].[Measure]
/
([Measures].[Measure], [Dim1].[Dim1].CurrentMember.Parent)
Thanks
In Analysis Services, your [Dim1].[Dim1]**.....IS SELECTED ON ROWS.........** could be coded as
Axis(1).Item(0).Item(0).Hierarchy IS [Dim1].[Dim1]
if you can assume there is only one hierarchy on the rows.
Here, Axis(1) returns the rows axis as set. I am not sure if this function is supported by Pentaho/Mondrian. Then, the first Item(0) selects the first tuple of this set, and the second one returns the first member of that tuple. Finally, the Hierarchy function returns the hierarchy of a member.
To extend this to queries containing up to three hierarchies in the rows, you would write
Axis(1).Item(0).Item(0).Hierarchy IS [Dim1].[Dim1] OR
Axis(1).Item(0).Item(1).Hierarchy IS [Dim1].[Dim1] OR
Axis(1).Item(0).Item(2).Hierarchy IS [Dim1].[Dim1]