Iccube: measure as a filter - dimensions

Iccube - Reporting:
I would like to use certain values of measures as a filter.
For example:
dimension: product -
measure: price
I would like to filter all products which are < 50€.
A workaround would be a second dimension "price" but I dont want that because than the schema will load much longer.
Optional: i can define the price as a custom property of the dimension.
Note: i dont want to use something like this
([product].CurrentMember.properties("price") = '50') because there are many different values
cheers j

You might solve this on the server or in the reporting.
In the server :
You can add a utility hierarchy similar to the one described here. As this applies only to one product you would need to do this as a secondary hierarchy of the dimension with the products (you need a new column with this info when loading the dimension).
In the reporting.
The filter is missing yet from the data wizard but you might enter an MDX that filters your products. You can do this with the MDX Filter function.
The point with this solution is if you query defines a subselect or a where clause and whether you want to use this when filtering your products. Using the query context means that if your query defines a particular filter, e.g. [MyCountryInFilter], it will be used when evaluating the filter measure.
Filter( [Products] , [Measures].[MyMeasure] )
will evaluate [MyMeasure] as ( [MyMeasures], [MyCountryInFilter] ). You can indeed make this independent from the filter by using
Filter( [Products], ( [Country].defaultmember, [MyMeasure] )
The more robust version to make this 'filter' independent is by using a static set. If the set is always the same you might create a static set (define it in the schema) as described here :
CREATE STATIC SET [MyFilteredProducts] as Filter( ...
it's also possible to define a set evaluated with a static context at request level
WITH
STATIC SET [MyFilteredProducts] as Filter( ...
...
hope it helps

Related

Filter in WHERE using Named Set

Is it possible to use an aggregated named set to filter queries in MDX? I don't want the set items in the result set so moved it to the WHERE, however this seems to cause all measures to return (null).
First, I build a set using a couple of members from a staff hierarchy:
WITH
SET [Combined] as {
[Staff].[Group].[Practice Group].&[04],
[Staff].[Group].[Practice Group].&[06]
}
Then I aggregate that set into a new member:
MEMBER [Staff].[Group].[Group Combo] AS Aggregate([Combined])
Usually I would then use this in my query as a reporting area, possibly with hierarchize (depending on the query) and everything is fine. However this time I needed to filter the data based on this combination of members e.g:
WHERE ([Staff].[Group].[Group Combo])
This gave me (null) values and if I used [Combined] I received a cyclical reference error, however using the below worked fine:
WHERE ({[Staff].[Group].[Practice Group].&[04],[Staff].[Group].[Practice Group].&[06]})
Am I overlooking something here? Or using the wrong approach? Maybe it is just a quirk of the cube I am querying?
I would say that the behaviour is related to the order in which the processor is executing the clauses within your query:
Logical order an MDX query is processed
WHERE happens before WITH
You mentioned that the following works fine - specifying explicit members in the where clause it is pretty standard and fast:
WHERE ({[Staff].[Group].[Practice Group].&[04],[Staff].[Group].[Practice Group].&[06]})
You could add it to a sub-select just as it is on the 0 axis:
SELECT
...
...
FROM
(
SELECT
{[Staff].[Group].[Practice Group].&[04],[Staff].[Group].[Practice Group].&[06]} ON 0
FROM [YourCube]
);

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)