Extracting second value from ordered list - sql-server-2012

The following gives me a list of the countries in alphabetical order.
How do I change it so that instead of returning the whole list it just returns the second country in this list? In terms of our cube this would just be the result for the Aland Islands.
SELECT
ORDER([Geolocation].[Geography].[Geography Country].MEMBERS,
[Geolocation].[Geography].CurrentMember.name, BASC ) ON ROWS,
[Measures].[DefaultMemberName] ON COLUMNS
FROM [MyCube]

You can use the item function; if I remember well it is 0-based :
ORDER( [Geolocation].[Geography] ... )(1)

Related

How to sort records in MDX query when numeric expression is used with TopCount function

I am trying to sort the Top 201 records in my SSAS cube either ascending or descending based on requirements in my C# code.
Here I a using Adventure Works Database, where [Reseller Order Count] is the measure and [Reseller].[Business Type] is the dimension.
Please find the details below here.
MDX Query For Ascending Sorting
SELECT{
[Measures].[Reseller Order Count]} ON COLUMNS ,NONEMPTY((TOPCOUNT(
(Order((([Reseller].[Business Type].[Business Type].ALLMEMBERS)), [Measures].[Reseller Order Count] ,ASC)),201,[Measures].[Reseller Order Count])),{
[Measures].[Reseller Order Count]}) ON ROWS FROM [Adventure Works] CELL PROPERTIES VALUE, FORMATTED_VALUE, FORMAT_STRING
Sorting Result:
In the following result, descending sorting is applied instead of ascending sorting.
While checking the documentation, I have found that by default the Descending sorting will be applied.
Link: https://learn.microsoft.com/en-us/sql/mdx/topcount-mdx?view=sql-server-ver15#remarks
Question:
My question is how to achieve ascending sorting as well as descending when the numeric expression is added in Top Count in MDX query in a generic manner?
Try changing the ASC keyword (to signify ascending order) to BASC instead. The B indicates that this will break the hierarchy of the [Reseller] dimension whose members are being listed.
The phrase "break the hierarchy" means that the ordering of values takes precedence over the ordering of the dimension's hierarchy.
(With ASC the measures are only ordered within items that are grouped together at the same level.)

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];

How filter only the children members in MDX?

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

Can RANK function be used anywhere other than the WITH clause

In a previous post I had this script:
WITH
SET [orderedSet] AS
ORDER(
[Operator].members,
[Operator].currentmember.name,
BASC
)
MEMBER [Measures].[newMeasure] AS
RANK(
[Operator].currentmember,
[orderedSet]
)
SELECT
[Measures].[newMeasure] ON COLUMNS,
[orderedSet] ON ROWS
FROM [ourCube]
Plus further reference to the MSDN page
Can the RANK function be used in any clauses other than WITH?
It's first argument is a tuple so I'm not sure how to use it in other clauses such as the SELECT.
It can be used anywhere where a numeric expression can be used.
Please note that in MDX, the axes in the select clause are sets, hence you cannot use Rank or any function that returns a numeric expression in an axis clause, but only functions returning sets (or some data types like tuples which are implicitly converted to sets).
And all members that appear in an expression returning a set have to be defined before you start with this expression. Hence, you cannot define them in the axis clause like you can use expressions to define result columns in SQL selects.
However, to literally answer your question, you can use Rank indirectly in the select clause in MDX e. g. if the outer function is Filter, which returns a set. The following is a slightly inefficient way to show the first three countries according to attribute order:
SELECT {[Measures].[Internet Sales Amount]}
ON COLUMNS,
Filter(
[Customer].[Customer Geography].[Country].Members as C,
Rank(C.Current, [Customer].[Customer Geography].[Country].Members) <= 3
)
ON ROWS
FROM [Adventure Works]
Some people use Rank within Generate to reverse sets, which would be another use of Rank that would be legal in the select clause.

Dividing tied RANKs using MDX

Still getting the hang of interpreting the MDX documentation on MSDN. So for the RANK function it has the following:
If a numeric expression is specified, the Rank function determines the
one-based rank for the specified tuple by evaluating the specified
numeric expression against the tuple. If a numeric expression is
specified, the Rank function assigns the same rank to tuples with
duplicate values in the set. This assignment of the same rank to
duplicate values affects the ranks of subsequent tuples in the set.
For example, a set consists of the following tuples, {(a,b), (e,f),
(c,d)}. The tuple (a,b) has the same value as the tuple (c,d). If the
tuple (a,b) has a rank of 1, then both (a,b) and (c,d) would have a
rank of 1. However, the tuple (e,f) would have a rank of 3. There
could be no tuple in this set with a rank of 2. If a numeric
expression is not specified, the Rank function returns the one-based
ordinal position of the specified tuple. The Rank function does not
order the set.
In the following script if two people are tied second for the highest salary I get the following salary ranks:
1
2
2
4
What I'd like to do is use the number of years in service to decide which of the tied people has the higher rank. Is this possible?
WITH
SET [OrderedPeople] AS
ORDER(
NONEMPTY(
[PeopleDimension].[PeopleHier].[NamesLevel].members,
{ //following means if one or the other is null
//then the row is not excluded
[Measures].[Salary],
[Measures].[NumYearsService]
}
),
[Measures].[Salary]
*
[Measures].[NumYearsService]
,
BDESC
)
MEMBER [Measures].[Salary_Rank] AS
RANK([PeopleDimension].[PeopleHier].CurrentMember,
[OrderedPeople],
[Measures].[Salary] //<<<how do I use numYearsService to decide ties?
)
SELECT
NON EMPTY
{
[Measures].[NumYearsService],
[Measures].[Salary],
[Measures].[Salary_Rank]
}
ON COLUMNS,
NON EMPTY
[OrderedPeople]
ON ROWS
FROM [ourCube]
WHERE
(
{TAIL([Date].[Date - Calendar Month].[Calendar Day],7)(0):
TAIL([Date].[Date - Calendar Month].[Calendar Day],7)(6)}
)
If you have the set already ordered, you use Rank without the third argument, i. e.
RANK([PeopleDimension].[PeopleHier].CurrentMember,
[OrderedPeople]
)
Rank returns the position that the first argument has in the set which is the second argument. The third argument is specifically used for the case when you want to have ties getting the same value. If you use the third argument, then for adjacent elements within the set, the third argument is checked, and the return value is the position of the first element within the set that has the same value for the third argument.
To order by several criteria in MDX, nest two orders within each other:
ORDER(
ORDER(
NONEMPTY(
[PeopleDimension].[PeopleHier].[NamesLevel].members,
{ //following means if one or the other is null
//then the row is not excluded
[Measures].[Salary],
[Measures].[NumYearsService]
}
),
[Measures].[NumYearsService]
,
BDESC
),
[Measures].[Salary],
BDESC
)
AS MDX Order is guaranteed to do a stable sort, when executing the outer sort, then the members that have the same salary do not change their relative order from the first sort, which means they keep being sorted by years in service.