Select one hierarchy on a dimension with multiple hierarchies - mdx

I do have a cube V that has a measure Q and some dimensions D, F.
In the dimension D I wanna have 2 hierarchies that share some common members, here they are (the 2 hierarchies are A and T and the common members are M and I):
-D
-A
+A
+M
+I
-T
+T
+M
+I
I'm trying with no success to create a MDX query to access either A and T:
select {[Measures].[Q]} ON COLUMNS,
{([F], [D].[A]} ON ROWS
from [V]
but I do get an error from JPivot using Mondrian saying that
Mondrian Error:MDX object '[D].[A]' not found in cube 'V'. So I cannot access neither.
This is my first attempt at MDX, so I recognize I might have missed something from the cube construction or the language understanding.

Usually that error is returned when the member you're referencing doesn't exist in your dimension. The right syntax to refer to a particular Hierarchy (aside from the default) is [Dimension.Hierarchy], so try this
select {[Measures].[Q]} ON COLUMNS,
{([F], [D.A])} ON ROWS
from [V]
Assuming your A hierarchy has an All member then it should work.
EDIT: I thought you couldn't do this in Mondrian but after trying it, it turns out you can: Try crossjoining the two hierarchies' members:
SELECT NON EMPTY {[Measures].[Q]} ON COLUMNS,
NON EMPTY CROSSJOIN([D.A].[Year].Members, [D.T].[Type].Members) ON ROWS
FROM [V]
The NON EMPTY functions will prevent combinations of the A and T hierarchies that do not have values from showing up in your output. Mind you, this will not really allow you to drill from Year down to Type, rather they will show side by side.

Related

MDX-How to return multiple measures

I'm trying to optimize a 2M row SSAS query into Power BI by using MDX prior to the Power Query. I have experience in T-SQL and found a website to help translate T-SQL experience into MDX, which was successful for some queries (basic rows/column selects, crossjoins, non empty, order by, filter, where). So now I want to get in my sales data which contains three dimensions and four measures but I get the following error:
Executing the query ...
Query (3, 1) The 'Measures' hierarchy appears more than once in the tuple.
Run complete
I attempted a few variations related to crossjoining the measures and the dimensions, only selecting one measure (which still took too long), and specifying members vs children.
'''
select
([Date].[OrderDate].children, [Customer].[CustID].children, [ProdLevel].[ProdNumber].children) on rows,
([Measures].[Revenue], [Measures].[Units], [Measures].[ASP], [Measures].[Profit]) on columns
from [RepProdDB]
where [ProdLevel].[Prod Description].[MyBusinessUnit]
'''
Looking up the error: "The 'Measures' hierarchy appears more than once in the tuple." is a bit vague to me as I have slight but probably incomplete understanding of tuples.
My hope is to have something that I can easily get in PivotTable OLAP, Power Pivot, and Power Query but using the actual MDX code. Thoughts?
So you need to understand the diffrence between tuples and sets.
select
non empty
(
[Date].[OrderDate].children,
[Customer].[CustID].children,
[ProdLevel].[ProdNumber].children
)
on rows,
{
[Measures].[Revenue],
[Measures].[Units],
[Measures].[ASP],
[Measures].[Profit]
}
on columns
from [RepProdDB]
where
[ProdLevel].[Prod Description].[MyBusinessUnit]

How to Overcome MDX Query Error When It Can't Find Specific Entity

When i run MDX query like:
select {[Measures].[all_accounts]} ON COLUMNS,
{{[Country].[Country].[Country].&[italy]}*
{[TD].[TD].[date].&[2016-09-02T03:00:00.000]:[TD].[TD].[date].&[2016-09-02T03:08:00.000]},
{[Country].[Country].[Country].&[Germany]}*
{[TD].[TD].[date].&[2016-08-16T04:00:00.000]:[TD].[TD].[date].&[2016-08-16T04:03:00.000]}}
ON ROWS
FROM [cube]
i get an error because 'italy' is not an entity found in Country dimension.
and no result is coming back.
i want to be able to run the mdx without necessarily knowing the entities names in the dimension and get back a result only for those that exists. in this example 'Germany'. how can i overcome this problem?
You can change the configuration of the server, icCube.xml, to convert not found members to null (it's risky).
icCube.mdxEvalUnknownMemberError
If you do not want to change this setting for the whole server you can use an annotation with each MDX query. For example, the following query will not return anything for the missing &[_FR] member:
//#prop( icCube.mdxEvalUnknownMemberError = false )
select {
[Geography].[Geo].[Country].&[FR_],
[Geography].[Geo].[Country].&[US]
} on 0 from [Sales]
Not a very positive answer I'm afraid but if you use member unique names such as [Country].[Country].[Country].&[italy] in a script then you will get an error if that member is not in the cube ... I don't believe there is a workaround.
I have to add that this 'limitation' has never caused me a problem.

SSAS: Two sets specified in the function have different dimensionality

I'm trying to run the following MDX query (I'm newbie in the matter):
WITH MEMBER [Measures].[Not Null SIGNEDDATA] AS IIF( IsEmpty( [Measures].[SIGNEDDATA] ), 0, [Measures].[SIGNEDDATA] )
SELECT
{[Measures].[Not Null SIGNEDDATA]} ON COLUMNS,
{[Cuenta].[818000_001],[Cuenta].[818000_G02]} ON ROWS
FROM [Notas_SIC]
WHERE ([Auditoria].[AUD_NA],[Concepto].[CONCEPTO_NA],[Entidad].[CCB],
[Indicador].[INDICADOR_NA],[Interco].[I_NONE],[Moneda].[COP],
[Tiempo].[2010.01],[Version].[VERSION_NA])
Where 818000_001 is a base member of my 'Cuenta' dimension, and 818000_G02 is a node or aggregation. I receive the following message:
"Two sets specified in the function have different dimensionality"
What am I doing wrong? If I put the query with only base members (many) or only differents aggregations, the result is ok as expected.
Thanks in advance!
By using commas in your WHERE clause, you are trying to create a set out of members from different dimensions. You should use asterisks to make a CROSSJOIN instead.
So replace this:
WHERE ([Auditoria].[AUD_NA],[Concepto].[CONCEPTO_NA],[Entidad].[CCB],
[Indicador].[INDICADOR_NA],[Interco].[I_NONE],[Moneda].[COP],
[Tiempo].[2010.01],[Version].[VERSION_NA])
With this:
WHERE ({[Auditoria].[AUD_NA],[Concepto].[CONCEPTO_NA],[Entidad].[CCB]} *
{[Indicador].[INDICADOR_NA],[Interco].[I_NONE],[Moneda].[COP]} *
{[Tiempo].[2010.01],[Version].[VERSION_NA]})
I added curly braces though I'm not sure if they're absolutely required.
This is maybe your problem:
{[Cuenta].[818000_001],[Cuenta].[818000_G02]} ON ROWS
You have put them as a set but you can only make a set out of members with the same dimensionality. From your description it sounds like [Cuenta].[818000_G02] is being classed as a different hierarchy which is unexpected.
Is [Cuenta].[818000_G02] created using the Aggregate function? Can you swap to using the Sum function? Does the script then work?
(not a great answer - just more questions?)
{[Cuenta].[818000_001],[Cuenta].[818000_G02]}
Your problem probably lies in the above statement. As is clear, they could be from different hierarchies(which is not clear from your example and I come to that below).
Try replacing the above with
{[Cuenta].[Hierarchy1].[818000_001]} * {[Cuenta].[Hierarchy2].[818000_G02]}
where Hierarchy1 and Hierarchy2 are the hierarchies to which these members belong. (If you are not sure, just try {[Cuenta].[818000_001]} * {[Cuenta].[818000_G02]}). I am assuming that the second aggregate members may be built on a different hierarchy and thus the engine is throwing an error.
It is generally a good habit to always use the fully qualified member name because then the SSAS engine has to spend less time in searching for the member.

How to do an aggregation in MDX similar to a 'sum over partition' statement in sql

I have a situation where I have a product and a time dimension, with a fact table of sales volume. Over time, various details about the product changes, with the except of the business key for the product. In my flat reporting from the cube, I want to include some aggregration at the 'business key' level, regardless of what other parts of the product dimension are shown.
In sql this would be trivial as something like:
select sum(volume) over (partition by productKey,year) as Total
Regardless of whatever else I had selected, the Total column would be aggregated only on those two fields.
In MDX I have managed to achieve the same result, but it seems like there must be a simpler way.
WITH MEMBER Measures.ProductKeyTotal AS
'SUM(([Product].[ProductKey],[Time].[Year]
,[Product].[Product Name].[Product Name].ALLMEMBERS
,[Volume Type].[Volume Type Id].[Volume Type Id].ALLMEMBERS)
,[Measures].[Volume])'
SELECT {[Measures].[Volume],[Measures].[ProductKeyTotal]} ON COLUMNS,
NONEMPTYCROSSJOIN ([Product].[ProductKey].[ProductKey].ALLMEMBERS
,[Time].[Time].[Year].ALLMEMBERS
,[Product].[Product Name].[Product Name].ALLMEMBERS
,[Volume Type].[Volume Type Id].[Volume Type Id].ALLMEMBERS) ON ROWS
FROM [My Cube]
WHERE ([Product].[Include In Report].&[True])
1) If I don't include the allmembers for the rows I don't want in the calculated member the total is not correct, is there a shortcut to force it to ignore all the dimensions other that what you specify?
Part of the reason I ask is that I need to add a bunch of other calculated members, some of which will be using parameters and if I use the method from the example above I am going to need to duplicate the same stuff in multiple places, and the code will get weighty.
Well, first of all, don't use NonEmptyCrossJoin--it's been deprecated. Use non empty and then the cross join operator (*).
It's important to understand how tuples and tuple sets work to answer your question. Essentially, any dimension not explicitly stated will always get the CurrentMember of a given dimension. Typically, this is DefaultMember, but if you have it set to something else in your query, that will change this up. The reason you have to specify ALLMEMBERS for those dimensions is because it will use CurrentMember, otherwise. You could just use the [All] member in lieu of trying to sum up ALLMEMBERS (especially if they're not flat!), which will give you a bit better performance.
The most performant way to do this is to add another Measure Group to your cube, and then remove the keys that don't apply to the measure from that Measure Group. This way, you get a native calculation for these rather than a run-time calculation (which tend to be slow, especially when you're adding up everything in your cube). Moreover, you can even set up some aggregation design on that Measure Group, and it will be very performant.

MDX WHERE NOT IN() equivalent in many-to-many dimension

I have a many-to-many dimension in my cube (next to other regular dimensions). When I want to exclude fact rows in my row count measure, I usually do something like the following in MDX
SELECT [Measures].[Row Count] on 0
FROM cube
WHERE ([dimension].[attribute].Children - [dimension].[attribute].&[value])
This might seem more complicated than needed in this simple example, but in this case the WHERE can grow sometimes, also including UNIONs.
So this works for regular dimensions, but now I have a many-to-many dimension. If I perform the trick above it does not produce the desired result, namely I want to exclude all rows that have that specific attribute in the many-to-many dimension.
Actually it does exactly what the MDX asks, namely count all rows, but ignore the specified attribute. Since a row in the fact table can have multiple attributes in a many-to-many dimension, the row will still be counted.
That's not what I need, I need it to explicitly exclude rows that have that dimension attribute value. Also, I might exclude multiple values. So what I need is something similar to T-SQL's WHERE .. NOT IN (...)
I realize that I can just subtract the resulting values from [attribute].all and [attribute].&[value], but that won't work any more when UNIONing multiple WHERE statements.
Anybody got a good idea on how to solve this?
Thanks in advance,
Delta
I have not tested this, but I think you could do this if you had an attribute that was at the same level of granularity as the rows (so probably implemented as a fact relationship).
So if you wanted to count the number of orders that did NOT have a product category of bikes (assuming a M2M relationship between OrderID and Category) then something like the following should work. (you can find more info on the EXISTS function in Books Online)
[Orders].[Order ID].[Order ID].Members
- EXISTS([Orders].[Order ID].[Order ID].Members
, [Product].[Category].&[Bikes]
, "Order Facts")
Although it could be quite slow as this sort of query is forcing the SSAS engine to add up a lot of facts from a low level.
Have you tried the EXCEPT command? It's syntax is like the following:
EXCEPT({the set i want}, {a set of members i dont want})
You could use the Filter function:
SELECT [Measures].[Row Count] on 0
FROM [cube]
WHERE Filter([dimension].[attribute].Children, [dimension].CurrentMember.MemberValue <> value)