The relevant structures from my cube are that I have a Hierarchy with "Class" and "SubClass". I also have a Measure called "Value" which is what im trying to obtain.
A simple query may look like:
SELECT
NON EMPTY ([Measures].[Value]) ON COLUMNS,
NON EMPTY ([Some Dimension].[Class Hierarchy].[Class]) ON ROWS
FROM [MyCube]
And I can obviously read the SubClass using the HIerarchy which is returned to Adomd.
My issue is twofold, firstly how would I "flatten" this hierarchy so as to receive both Class and SubClass as discrete members in the CellSet? This does not work:
SELECT
NON EMPTY ([Measures].[Value]) ON COLUMNS,
NON EMPTY (
[Some Dimension].[Class Hierarchy].[Class],
[Some Dimension].[Class Hierarchy].[Sub Class]
) ON ROWS
FROM [MyCube]
The Class Hierarchy hierarchy is used more than once in the Crossjoin function
Second issue, what I actuually need to do is filter the above on particular classes, again this wont work for the same reason as above.
SELECT
NON EMPTY ([Measures].[Value]) ON COLUMNS,
NON EMPTY (
{[Some Dimension].[Class Hierarchy].[Class].&[ClassA],[Some Dimension].[Class Hierarchy].[Class].&[ClassB]},
[Some Dimension].[Class Hierarchy].[Sub Class]
) ON ROWS
FROM [MyCube]
Any help much appreciated. MDX is driving me nuts!
You are missing the MEMBERS property on your dimension.
For your first example try this:
SELECT
NON EMPTY ([Measures].[Value]) ON COLUMNS,
NON EMPTY {(
[Some Dimension].[Class Hierarchy].[Class].MEMBERS,
[Some Dimension].[Class Hierarchy].[Sub Class].MEMBERS)} ON ROWS
FROM [MyCube]
For your second example try this:
SELECT
NON EMPTY ([Measures].[Value]) ON COLUMNS,
NON EMPTY {(
[Some Dimension].[Class Hierarchy].[Class].&[ClassA],
[Some Dimension].[Class Hierarchy].[Class].&[ClassB],
[Some Dimension].[Class Hierarchy].[Sub Class].MEMBERS)} ON ROWS
FROM [MyCube]
Use Subqueries in your WHERE Clause.
MDX will always restrict the use of one dimension on one Axis only.
Sub Query is a way to get around that. I recently learnt this trick after MDX drove me nuts as well..
Hi this query worked for me.
SELECT NON EMPTY { [Measures].[App Count] }
ON COLUMNS,
NON EMPTY
{(
EXISTING
(
[MART TIME DIM].[Date].[Date] .MEMBERS) *
[New Ren DIM].[New Ren CODE].[New Ren CODE].ALLMEMBERS
)}
ON ROWS FROM [SubmissionCube]
where
({
[MART BROKER DIM].[BROKER ID].&[10812]},{[MART TIME DIM].[Year].&[2015],
{[MARTTIME DIM].[Year].&[2016]}
})
Please be carefull with the '}' in the where clause as the query has.
Related
Problem
I need to create a report which will list a number of accounts that match certain criteria - simulationDate, statisticPeriod, region.
Right now my query looks like this:
WITH MEMBER [Measures].[Count] as 1
SELECT [Measures].[Count] ON COLUMNS,
NON EMPTY
Crossjoin(
[Account].[Account Number].ALLMEMBERS,
{[simulationDate].[day].&[10010101]},
{[statisticPeriod].[period].&[201201]},
{[region].[code].&[SO]}
)
ON COLUMNS
FROM [myWH]
Is this cross-dimensional filtering okay?
This is slightly more modern using the * notation instead of the Crossjoin function:
WITH
MEMBER [Measures].[Count] AS 1
SELECT
[Measures].[Count] ON COLUMNS
,NON EMPTY
[Account].[Account Number].ALLMEMBERS*
{[simulationDate].[day].&[10010101]}*
{[statisticPeriod].[period].&[201201]}*
{[region].[code].&[SO]} ON COLUMNS
FROM [myWH];
I'm assuming that your custom measure [Measures].[Count] is just a place-holder?
This table will be very wide if you have that cross-join on COLUMNS but that might just be a typo:
WITH
MEMBER [Measures].[Count] AS 1
SELECT
[Measures].[Count] ON COLUMNS,
NON EMPTY
[Account].[Account Number].ALLMEMBERS*
{[simulationDate].[day].&[10010101]}*
{[statisticPeriod].[period].&[201201]}*
{[region].[code].&[SO]} ON ROWS
FROM [myWH];
You have added the keywords NON EMPTY in front of the rows cross-join. This is telling the processor to exclude any rows that are empty - empty for [Measures].[Count] ....but this measure is never empty it is always equal to 1. So the following without Non Empty should return exactly the same result:
WITH
MEMBER [Measures].[Count] AS 1
SELECT
[Measures].[Count] ON COLUMNS,
[Account].[Account Number].ALLMEMBERS*
{[simulationDate].[day].&[10010101]}*
{[statisticPeriod].[period].&[201201]}*
{[region].[code].&[SO]} ON ROWS
FROM [myWH];
So in terms of filtering you aren't doing any - what sort of filtering do you need? If you replace [Measures].[Count] with an actual measure from your cube and use the NON EMPTY then you should see a lot less rows:
SELECT
[Measures].[ReplaceWithActualMeasure] ON COLUMNS,
NON EMPTY
[Account].[Account Number].ALLMEMBERS*
{[simulationDate].[day].&[10010101]}*
{[statisticPeriod].[period].&[201201]}*
{[region].[code].&[SO]} ON ROWS
FROM [myWH];
In the end I ended up using the filters as my columns, and letting the NON EMPTY clause take care of the filtering:
SELECT
NON EMPTY
{[simulationDate].[day].&[10010101]} *
{[statisticPeriod].[period].&[201201]} *
{[region].[code].&[SO]}
ON COLUMNS,
NON EMPTY
[Account].[Account Number].ALLMEMBERS
ON ROWS
FROM [myWH]
SELECT NON EMPTY { [Measures].[Total Value],[Measures].[Value less than 30],
[Measures].[Value less than 60],[Measures].[Value less than 90],[Measures].[Value less than 150],
[Measures].[Value less than 180],[Measures].[Value less than 365],[Measures].[Value more than 365]}
DIMENSION PROPERTIES CHILDREN_CARDINALITY, PARENT_UNIQUE_NAME ON COLUMNS,
NON EMPTY {[Combined].[Drill Down Path 4].[Supplier Name].ALLMEMBERS }
DIMENSION PROPERTIES MEMBER_CAPTION ON ROWS FROM [InventoryAge]
WHERE ( [Calendar].[Report Days].[All Members].&[All].&[WantInReport].&[2].&[20141031] )
for the where clause I want to get the last element of my calender dimension. The calender dimension is as follows
What is the best way to achieve this
Try something like this:
WHERE ( [Calendar].[Report Days].[All Members].[All].[WantInReport].[Last Days].LastChild )
You should be able to use the name of your members (but with removing & in front of them), that's why .&[WantInReport]. become .&[WantInReport]..
I'd rather use .[Last Days]. than .&[2]., easier to understand when you look later at the query.
Finally using .LastChild gives you last item of your selected branch.
When I run this mdx query, works fine (get the children members from a hierarchy level):
select {} on columns,
[Dimension].[hierarchy].[level].children on rows
from [Cube]
But, when I add some tuple on rows, doesn't filter filter the children members (shows all the members) :S
select {} on columns,
[Dimension].[hierarchy].[level].children
* [Dimension2].[hierarchy2].[level2].allmembers on rows
from [Cube]
* is a cross join - you will get the Cartesian product of [Dimension].[hierarchy].[level].children and [Dimension2].[hierarchy2].[level2].allmembers because they are different dimensions.
If they were two hierarchies from the same dimension then auto exist behaviour would limit the results e.g. Year2014 crossed with month should just show the months in 2014.
Try using DESCENDANTS function + you might not require NULLs so try the NON EMPTY
SELECT
{} ON COLUMNS,
NON EMPTY
DESCENDANTS(
[Dimension].[hierarchy].[level].[PickAHigherUpMember],
[Dimension].[hierarchy].[PickTheLevelYouWantToDrillTo]
)
*
[Dimension2].[hierarchy2].[level2].allmembers ON ROWS
FROM [Cube]
if you look at the mdx language reference for children, you will also find another example of how to use the function with a hierarchy in stead of a member_expression.
http://msdn.microsoft.com/en-us/library/ms146018.aspx
but it won't work with a hierarchy level.
Maybe the row expression was initialy a hierarchy that you've have changed into a level expression.
in the following a similar working mdx with a hierarchy on rows:
select {} on 0,
[Product].[Model Name].children
*
[Geography].[Country].[All Geographies]
on 1
FROM [Adventure Works
Philip,
I guess you want only those rows where the children have a value on the default measure. In that case you could try the following:
select {} on columns,
Nonempty([Dimension].[hierarchy].[level].children
* [Dimension2].[hierarchy2].[level2].allmembers) on rows
from [Cube]
Now if, for the children, you'd need all the members from Dimension2 then you could try:
select {} on columns,
Nonempty([Dimension].[hierarchy].[level].children, [Dimension2].[hierarchy2].[level2].allmembers)
* [Dimension2].[hierarchy2].[level2].allmembers) on rows
from [Cube]
In the second case the Nonempty function takes a second parameter and the cross join is done with the result of the Nonempty function. For the documentation on Nonempty including the usage of the second parameter see https://learn.microsoft.com/en-us/sql/mdx/nonempty-mdx
In my time dimensions i have 2013,2014,2015.
How can i make a Union in this mdx so i get the results from this mdx for all thoose years and not only for 2014 like in the example..
select NON EMPTY {[Measures].[Absatz Plan], [Measures].[Umsatz Plan], [Measures].[Absatz Effektiv], [Measures].[Umsatz Effektiv]} ON COLUMNS,
NON EMPTY Crossjoin(Hierarchize({([Time].[2014], [Artikel].[All Artikels], [Markt].[All Markts])}), {[Version].[14], [Version].[16], [Version].[18]}) ON ROWS
from [Budget]
Just apply CrossJoin twice:
select NON EMPTY
{[Measures].[Absatz Plan], [Measures].[Umsatz Plan], [Measures].[Absatz Effektiv], [Measures].[Umsatz Effektiv]}
ON COLUMNS,
NON EMPTY
CrossJoin(
Crossjoin(
{[Time].[2013], [Time].[2014], [Time].[2015]},
{([Artikel].[All Artikels], [Markt].[All Markts])}
),
{[Version].[14], [Version].[16], [Version].[18]}
)
ON ROWS
from [Budget]
I removed the Hierarchize, as I think it is not necessary in this context. It would order its argument by the order defined for the hierarchy in the cube. If the order of the result seems wrong, you could re-add it.
I have an MDX query of the following form, which I am using with ActivePivot. I need to filter the results (in my on rows), by the presence of a part of string in another dimension (columns):
SELECT
NON EMPTY Hierarchize({[CODE].[CODE].Members}) ON ROWS,
NON EMPTY Hierarchize({Filter([RELEVANCE].Members, InStr([RELEVANCE].CurrentMember.Name, "n/a") > 0)}) ON COLUMNS
FROM [CUBE]
WHERE ([Measures].[contributors.COUNT])
The performance of this query is very poor with the filter/instr. I think I can understand that in that it presumably 'scans' through all of the members.
Is there another way to acheive what I want, but with better performance.
Thanks
If your RELEVANCE dimension has 3 levels and "n/a" appears on the last one you can write something like this:
SELECT
NON EMPTY [CODE].[CODE].Members ON ROWS,
NON EMPTY Hierarchize({[RELEVANCE].Levels(0).Members,
[RELEVANCE].Levels(1).Members,
Filter([RELEVANCE].Levels(2).Members, InStr([RELEVANCE].CurrentMember.Name, "n/a") > 0)}) ON COLUMNS
FROM [CUBE]
WHERE ([Measures].[contributors.COUNT])
It will reduce the number of useless filter checks.
You can also add to your cube another dimension with a level with 2 members : "n/a" and "not n/a".
In this case the query will become:
SELECT
NON EMPTY [CODE].[CODE].Members ON ROWS,
NON EMPTY [RELEVANCE].Members ON COLUMNS
FROM [CUBE]
WHERE ([Measures].[contributors.COUNT], [the new dimension].[...].[not n/a])
but this will change the value of your totals.