How to get the last, non empty 10 members with MDX? - mdx

I have an MDX query:
SELECT
NON EMPTY {Hierarchize({[Measures].[Rating]})} ON COLUMNS,
NON EMPTY {Hierarchize({[Response].[Response Name].Members})} ON ROWS
FROM [Ratings]
That returns a table of Response Names to Response count. This query returns a row for ALL responses, though, and I just want the most recent 10 responses.
I tried to do this using HEAD like so:
SELECT
NON EMPTY {Hierarchize({[Measures].[Rating]})} ON COLUMNS,
HEAD(NON EMPTY {Hierarchize({[Response].[Response Name].Members})}, 10) ON ROWS
FROM [Ratings]
but it gives an error "Syntax error at line 3, column 18, token 'NON'"
If I remove the NON EMPTY, then it works as I would expect (returns only 10 members), but then it includes the empty Ratings.
How can I use NON EMPTY and HEAD together? (Or accomplish the same thing another way)

I believe it is already a bit late for the answer, but here's the solution I used (I was having the same problem):
select {[Measures].[Percentage Present]} ON COLUMNS,
Head(Filter([Student].[Student].AllMembers, not isEmpty([Measures].[Percentage Present])),10) ON ROWS
from [Attendance]
Head + Filter(, not isEmpty([measure])) did the trick!

Not sure to understand what you mean by 'last' but here is a statement using the NonEmpty function instead of the NON EMPTY keywords:
SELECT
NON EMPTY [Measures].[Rating] ON COLUMNS,
HEAD( NonEmpty(
[Response].[Response Name].Members,
[Measures].[Rating]
),
10
) ON ROWS
FROM [Ratings]

Related

MDX Query - Non Empty on 1 Axis

I am trying to eliminate a null value from a result set. I am querying only first level dimension data to add to my selection box.
There is a #null value that gets returned with the query.
select {} on columns,
NON EMPTY{[Markets].[All Markets].Children}) on rows
from [SteelWheelsSales]
And the above query does not work since its not against any measure. But i want only the list Markets in the first level to be displayed in my selection box.
Rather than NON EMPTY try NonEmpty:
SELECT
{} ON 0,
NonEmpty([Markets].[All Markets].Children) ON 1
FROM [SteelWheelsSales];
Try filtering instead,
SELECT
{} ON COLUMNS,
Filter( [Markets].[All Markets].Children, not IsEmpty ( [Measures].[Sales]) ) ON ROWS
FROM [SteelWheelsSales];

MDX date range with NON EMPTY clause is not slicing the data for the range

I am working to optimize the query time. But in my cases, case 1 and case 2 are returning the same result. case 1 should return result for a particular data range i.e. [time].[2015].[5].[10] : [time].[2015].[6].[9] instead it is returning only for [time].[2015].[6].[9] as the result of case 2. case 1 returns the correct result i.e. data for the range but only if you remove the non empty clause. removing the non empty clause means it will search the entire data sets which is again taking lots of time. again case 3 returns correct result but operation is even more time then the first approach. Anybody facing such issue or can guide me to for the problem.
CASE 1
WITH
MEMBER [Measures].[abc_type] AS
[abc].CurrentMember.Properties("abc_type")
MEMBER [Measures].[abc_desc] AS
[abc].CurrentMember.Properties("abc_desc")
MEMBER [Measures].[abc_class] AS
[abc].CurrentMember.Properties("abc_class")
SELECT
NON EMPTY
{
[Measures].[abc_type]
,[Measures].[abc_desc]
,[Measures].[abc_class]
} ON COLUMNS
,NON EMPTY
Filter
(
{[abc].[abc_id].MEMBERS}
,St_contains
(
[district].[district_id].[1].Properties("the_geom")
,[abc].CurrentMember.Properties("the_geom")
)
) ON ROWS
FROM [analytics_cube]
WHERE
[time].[2015].[5].[10] : [time].[2015].[6].[9];
CASE 2
WITH
MEMBER [Measures].[abc_type] AS
[abc].CurrentMember.Properties("abc_type")
MEMBER [Measures].[abc_desc] AS
[abc].CurrentMember.Properties("abc_desc")
MEMBER [Measures].[abc_class] AS
[abc].CurrentMember.Properties("abc_class")
SELECT
NON EMPTY
{
[Measures].[abc_type]
,[Measures].[abc_desc]
,[Measures].[abc_class]
} ON COLUMNS
,NON EMPTY
Filter
(
{[abc].[abc_id].MEMBERS}
,St_contains
(
[district].[district_id].[1].Properties("the_geom")
,[abc].CurrentMember.Properties("the_geom")
)
) ON ROWS
FROM [analytics_cube]
WHERE
[time].[2015].[6].[9];
CASE 3
WITH
MEMBER [Measures].[abc_type] AS
[abc].CurrentMember.Properties("abc_type")
MEMBER [Measures].[abc_desc] AS
[abc].CurrentMember.Properties("abc_desc")
MEMBER [Measures].[abc_class] AS
[abc].CurrentMember.Properties("abc_class")
MEMBER [time].[newtime] AS
Aggregate([time].[2015].[5].[10] : [time].[2015].[6].[9])
SELECT
NON EMPTY
{
[Measures].[abc_type]
,[Measures].[abc_desc]
,[Measures].[abc_class]
} ON COLUMNS
,NON EMPTY
Filter
(
{[abc].[abc_id].MEMBERS}
,St_contains
(
[district].[district_id].[1].Properties("the_geom")
,[abc].CurrentMember.Properties("the_geom")
)
) ON ROWS
FROM [analytics_cube]
WHERE
[time].[newtime];
Ranges of time are always evaluated by Mondrian as a full level scan. It will load all of the members of the given time level and will start iterating over the members until it finds the first bound. It will then create a sublist up until the last member of the range.
There is an enhancement request filed to turn ranges into SQL predicates here.
If you get a chance to test the prototype code, let us know how it works for you

MDX Query, how to select first and last year of an event's period

I have a publications datamart from teachers of my university, I would like to select the list of teachers with how much books they wrote and in period while them publicated the books.
Example
Teacher - Last Year of pubblication - Number of Books
Teacher A - 2014 - 200 books
I tried to do something like:
WITH MEMBER [Measures].[LastYear] AS
'(ClosingPeriod([Anno].[Anno])
,[Autore].[Nome].CurrentMember)'
SELECT
{[Measures].[Unita (Libri)],[Measures].[LastYear]} ON COLUMNS,
NON EMPTY
[Autore].[Nome].Members ON ROWS
FROM [Pubblicazioni]
but the field last year is alway void, if i try to change the second part of ClosingPeriod with [Measures].[Unita (libri)] it is empty too... How should i implement that query? I'm a bit confused about
EDIT
select [Measures].[Libri] ON COLUMNS,
crossjoin([Autore.default].[Nome].[Fazzinga, Bettina], tail(NonEmptyCrossJoin([Autore.default].[Nome].[Fazzinga, Bettina], [Anno.default].[Anno].Members), 1).Item(0).Item(1)) ON ROWS
from [Pubblicazioni]
This one is working great for the teacher [Fazzinga, Bettina], but the query stops to work while i doing
select [Measures].[Libri] ON COLUMNS,
crossjoin([Autore.default].[Nome].Members, tail(NonEmptyCrossJoin([Autore.default].[Nome].CurrentMember, [Anno.default].[Anno].Members), 1).Item(0).Item(1)) ON ROWS
from [Pubblicazioni]
Measures needs some form of value or string to return, I think that is why your measure is returning void as ClosingPeriod is returning a member rather than value.
The following is not tested:
WITH MEMBER [Measures].[LastYear] AS
'(Tail(
nonempty(
[Anno].[Anno]
,([Autore].[Nome].CurrentMember, [Measures].[Unita (Libri)])
)
).item(0).item(0).MEMBERVALUE)'
SELECT
{[Measures].[Unita (Libri)],[Measures].[LastYear]} ON COLUMNS,
NON EMPTY
[Autore].[Nome].Members ON ROWS
FROM [Pubblicazioni]
Try this one instead:
SELECT
[Measures].[Libri] ON COLUMNS
,Generate
(
[Autore.default].[Nome].MEMBERS
,Tail
(
//NonEmptyCrossJoin <<hopefully nonempty is enough
NonEmpty
(
[Autore.default].[Nome].CurrentMember * [Anno.default].[Anno].MEMBERS
)
,1
) //.Item(0).Item(1) //<<don't believe this is required
) ON ROWS
FROM [Pubblicazioni];
I finally found a way to get it... Natively, every calculated member in the clause "WITH MEMBER" are treated as information of cube. In my case, if i do max("xpression of years when author worked") it will give the number of books he wrote in the relative max year. To avoid this, there is a construct called SetToStr() that will print the year as a String (something like [Hyerarchie].[Level].[Value]). The string can simple cutted with left() and right() condition. Here is the result:
WITH MEMBER [Measures].[Anno prima pubblicazione] AS 'left(right(settostr(head(extract(nonemptycrossjoin([Anno].[Anno].Members, nonemptycrossjoin([Libro].[Titolo].Members,[Autore].[Nome].CurrentMember)),[Anno]),1)),6),4)'
MEMBER [Measures].[Anno ultima pubblicazione] AS 'left(right(settostr(tail(extract(nonemptycrossjoin([Anno].[Anno].Members, nonemptycrossjoin([Libro].[Titolo].Members,[Autore].[Nome].CurrentMember)),[Anno]),1)),6),4)'
SELECT {[Measures].[Anno prima pubblicazione],[Measures].[Anno ultima pubblicazione]} ON COLUMNS,
[Autore].[Nome].Members ON ROWS
FROM [Pubblicazioni]
This query work in this way:
1) extract books for the current author with nonemptycrossjoin([Libro].[Titolo].Members,[Autore].[Nome].CurrentMember) so i get the tuple ;
2) I let the year join the previous tuple with nonemptycrossjoin([Anno].[Anno].Members,);
3) In my case the DM is ordered yet for year, in other case we should use even the function order;
4) we don'n need all that things, so we trash what we doesn't need using extract(,[Anno]), this mean i will maintain only the values of hierarchy [Anno];
5) we just need the first entry of the ordered list of years and we use head() function;
6) we can't use the value yet or MDX will count entries in the fact table for the value of [Anno] we selected, so we transform it as string with setToStr();
7) the value is still dirty, cause the string has hiearchy too, so we clean it using left() and right() function (a year is always composed by 4 chars).
It is a little big function, but this is the only one worked for me :)

Force mdx query to return column names

When connecting from powerpivot to SSAS, I got the following problem - if for some reason no rows are returned by mdx query, no column names are returned either and powerpivot gives an error. When executing such a query in SSMS I got 0 rows if mdx returns nothing and 2 rows if mdx returns 1 row (column names and the row itself). So - can I somehow force SSAS to return column names?
Query currently looks a bit like this:
SELECT NON EMPTY {[Measures].[Measure1]} ON COLUMNS,
NON EMPTY {Filter([DimLocalDate].[Date].&[20110101]:[DimLocalDate].[Date].&[20120101],
[JobStatus].[JobStatus].&[1] } ON ROWS
FROM [TheCube]
In my app customer can specify dates and status value. If no results are found I would expect an empty result set, but instead I got an error.
Thanks.
re SSIS error: [MEMBER_CAPTION] cannot be found at the datasource.
Thanks your solution helped me.
I had the same issue using SSIS, SSAS to output a flat file report
i'll post an extended example to help others define the dummy set.
Please note that the date is inserted into MDX script dynamically.
SSIS throws an exception when no data exists for the date, and therefore no results are returned.
This messes up the column order
--create a blank set so that data is still returned when there are no results for that date
set [BlankRowSet] as
([Activity Period].[Days].[Day].&[2014-02-02T00:00:00], [Well].[Location].[Location].&[])
--create the active set as the crossjoin between Days, Wells
set [ActiveSet] as
nonempty([Activity Period].[Days].[Day].members * [Well].[Location].[Location].members )
SET [RealSet] as IIF(COUNT([ActiveSet]) > 0, [ActiveSet], {[BlankRowSet]})
select {[Measures].[Total boe]} ON COLUMNS
,[RealSet] ON ROWS
FROM
(select {[Activity Period].[Days].[Day].&[2014-02-02T00:00:00]:[Activity Period].[Days].[Day].& [2014-02-02T00:00:00]} on 0 from [Volumes] )
where
[Scenario].[All Scenarios].[Category].&[PVR Sales Estimates]
I will check before the select if your NonEmpty clause will return a void set, and in that case put on row a dummy set that will be return to powerpivot at least 1 row.
Something like:
WITH
SET [mySet] as NON EMPTY ({Filter([DimLocalDate].[Date].&[20110101]:[DimLocalDate].[Date].&[20120101], [JobStatus].[JobStatus].&[1] })
SET [myRealSet] as IIF(COUNT([mySet]) > 0, [mySet], {[DummySet]})
SELECT NON EMPTY {[Measures].[Measure1]} ON COLUMNS,
[myRealSet] ON ROWS
FROM [TheCube]
would help?

Performance when using a filter and Instr in a MDX query

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.