MDX order doesn't work - mdx

I'm using the AdventureWorks Cube and MS SQL 2017 to learn MDX.
I'd like to return the top five selling subcategories of products, based on Internet Sales Amount:
SELECT Subset
(Order
([Product].[Product Categories].[SubCategory].members
,[Measures].[Internet Sales Amount]
,DESC
)
,0
,5
)
ON 0
FROM [Adventure Works]
The returned results are not sorted properly. Is there anything I did wrong?
Road Bikes Mountain Bikes Touring Bikes Tires and Tubes Helmets
$29,358,206.96 $26,492,684.38 $10,451,490.22 $925.21 $258,712.93
I also tried BDESC, seems to get the same result.

This query will help explain what happened. It was sorting correctly, but then it was displaying the default measure on the screen since you didn't specify the measure to display, only the measure to sort by:
SELECT {[Measures].[Internet Sales Amount], [Measures].DefaultMember} on 0,
Subset
(Order
([Product].[Product Categories].[SubCategory].members
,[Measures].[Internet Sales Amount]
,DESC
)
,0
,5
)
ON 1
FROM [Adventure Works]
I would recommend using that query but removing [Measures].DefaultMember and you should get the results you expect.

You want the TOPCOUNT MDX function
SELECT
[Measures].[Internet Sales Amount] ON COLUMNS
, TOPCOUNT([Product].[Subcategory].[Subcategory].MEMBERS,5,[Measures].[Internet Sales Amount]) ON ROWS
FROM
[Adventure Works]

Related

Sum of Previous months Sales with MDX

The below query works okay.
With Member PyMonthSales as
SUM(PARALLELPERIOD([Date].[Calendar].[Month], 1),[Measures].[Internet Sales Amount])
select
{PyMonthSales} on Columns,
[Date].[Calendar].[Month] on Rows
FROM
(
Select {
[Date].[Calendar].[Month].&[2006]&[5], [Date].[Calendar].[Month].&[2006]&[4]
} on Columns
From [Adventure Works]
)
But I just want one Grand total. So I removed the rows, on the above query
With Member PyMonthSales as
SUM(PARALLELPERIOD([Date].[Calendar].[Month], 1),[Measures].[Internet Sales Amount])
select
{PyMonthSales} on Columns
FROM
(
Select {
[Date].[Calendar].[Month].&[2006]&[5], [Date].[Calendar].[Month].&[2006]&[4]
} on Columns
From [Adventure Works]
)
This is where the problem starts. Returns null. Any assistance would be great.
Thanks for your time.
Naz
It ended up a bit messy!!
WITH
MEMBER [Measures].x AS
Aggregate
(
Generate
(
{
[Date].[Calendar].[Month].&[2006]&[5]
,[Date].[Calendar].[Month].&[2006]&[4]
}
,{
ParallelPeriod
(
[Date].[Calendar].[Month]
,1
,[Date].[Calendar].CurrentMember
)
}
)
,[Measures].[Internet Sales Amount]
)
SELECT
x ON 0
FROM [Adventure Works];
The thing I kept forgetting was the curly brackets around the ParallelPeriod section - without those an exception is raised because Generate always wants a SET as its second argument.

MDX query for bottomcount function

SELECT
[Measures].[Internet Sales Amount] ON COLUMNS
,BottomCount
(
NonEmpty([Customer].[Customer].[Customer].MEMBERS)
,10
,[Measures].[Internet Sales Amount]
) ON ROWS
FROM [Adventure Works]
WHERE
[Date].[Calendar].[Calendar Year].&[2005];
The above query is showing me result having last 10 customer names with NULL measure value. I am using Adventure works Cube.
As per my understanding "bottomcount" is not working fine with where clause in "mdx" query. I want to fetch last 10 customer names for 2005 with measure value and hopefully i am looking for solution without using keyword "DESCENDANTS".
Please let me know in case, I am doing something wrong.
Give this a try:
bottomcount(
nonempty(
[Customer].[Customer].[Customer].Members
,[Measures].[Internet Sales Amount]
)
,10
,[Measures].[Internet Sales Amount]
)
You were getting the Customer names with NULL because in OLAP you are doing the cartesian product between the 2 dimensions (Measures is a special dimension, but it still acts as a dimension) it does not matter that you don't have values it will still crossjoin the members in your 2 sets and unless you request just the nonempty ones it will still give you the NULLs.
And if you'd like their full internet sales amount then move some of the logic into the WITH clause:
WITH
SET bot AS
NonEmpty
(
[Customer].[Customer].[Customer].MEMBERS
,(
[Measures].[Internet Sales Amount]
,[Date].[Calendar].[Calendar Year].&[2005]
)
)
SELECT
[Measures].[Internet Sales Amount] ON COLUMNS
,BottomCount
(
bot
,10
,[Measures].[Internet Sales Amount]
) ON ROWS
FROM [Adventure Works];

How to get an "(all)" value for a level in a user defined hierarchy in SSAS/MDX

I am trying to work out how I can get a total for a level in a user defined hierarchy. For example if I do (using Adventure works here):
SELECT [Measures].[Internet Sales Amount] ON 0,
([Date].[Calendar Year].ALLMEMBERS * [Date].[Month of Year].ALLMEMBERS) ON 1
FROM [Adventure Works]
I get totals for each pair of year/month values.
How can I rewrite this query using the Calendar user hierarchy in the Date dimensions? Eg something like:
SELECT [Measures].[Internet Sales Amount] ON 0,
([Date].[Calendar].[Year] * [Date].[Calendar].[Month]) ON 1
FROM [Adventure Works]
You can use
SELECT [Measures].[Internet Sales Amount] ON 0,
Hierarchize([Date].[Calendar].[Calendar Year] + [Date].[Calendar].[Month]) ON 1
FROM [Adventure Works]
This will show you each year containing its value (which is the sum of the months contained in it) before the months.
The + is the short form of Union in MDX, and Hierarchize sorts a set in hierarchical order, which means parents before children.
And if you want something similar to your first result, the closest thing I can imagine would be via calculated measures like this:
WITH Member Measures.Year AS
IIf([Date].[Calendar].CurrentMember.Level IS [Date].[Calendar].[Calendar Year],
[Date].[Calendar].CurrentMember.Name,
Ancestor([Date].[Calendar].CurrentMember, [Date].[Calendar].[Calendar Year]).Name
)
Member Measures.Month AS
IIf([Date].[Calendar].CurrentMember.Level IS [Date].[Calendar].[Month],
[Date].[Calendar].CurrentMember.Name,
'All Months'
)
SELECT {
Measures.Year,
Measures.Month,
[Measures].[Internet Sales Amount]
}
ON 0,
Hierarchize([Date].[Calendar].[Calendar Year] + [Date].[Calendar].[Month]) ON 1
FROM [Adventure Works]
Note that calculated members need not return numbers, they can as well return strings.
Using allmembers as you have it should return you the ALL line and then each year and each month. If you are interested in only the all line you can change you query to:
SELECT [Measures].[Internet Sales Amount] ON 0,
([Date].[Calendar Year] * [Date].[Month of Year]) ON 1
FROM [Adventure Works]
Notice how it is specifying only the Dimension and the hierarchy.
If you wanted to get the data without the all line use the following:
SELECT [Measures].[Internet Sales Amount] ON 0,
([Date].[Calendar Year].children * [Date].[Month of Year].children) ON 1
FROM [Adventure Works]

MDX SSAS - Max Date in Measure

Just need to get MAX date in ALL my Measures in the Cube. For instance, DateID is a Dimention, [Measure].[First Measure],...,...,[Second Measure].
How to get list of MAX(DateID) from all Measures in my Cube.
The following will get you the max date value associated with each measure...but you will have to manually create a calculated member corresponding to each measure.
WITH
MEMBER [Measures].[Max Date - Internet Sales Amount] AS
TAIL(
NONEMPTY(
[Date].[Date].[Date]
,[Measures].[Internet Sales Amount]
)
,1
).Item(0).MemberValue
MEMBER [Measures].[Max Date - Reseller Sales Amount] AS
TAIL(
NONEMPTY(
[Date].[Date].[Date]
,[Measures].[Reseller Sales Amount]
)
,1
).Item(0).MemberValue
SELECT
{
[Measures].[Max Date - Internet Sales Amount],
[Measures].[Max Date - Reseller Sales Amount]
} ON 0
FROM
[Adventure Works]
If you want to get the single max date across all measures in the cube, you'll need to take a different approach.

SSAS - Sum of Top or Bottom

SELECT
[Measures].[Internet Sales Amount] ON COLUMNS
,Tail
(
[Date].[Calendar Year].[Calendar Year].MEMBERS
,2
) ON ROWS
FROM [Adventure Works];
Above MDX query gives me output as :
Year Internet Sales Amount
CY 2003 $9,791,060.30
CY 2004 $9,770,899.74
I understood how this query worked but I want to create Calculated measure in a cube which will always give me sum of bottom 2 years. How to do this? I am a newbie to SSAS. I am good at designing simple measures and dimensions but when it comes to using MDX, I am mostly stuck.
PS: I tried using TopCount, BottomCount etc but here I want to order by "Year", which is a dimension.
Any help would be appreciated.
Thanks,
Parry
The following query calculates a measure for sum the the last 2 years of the Date dimension:
WITH
MEMBER [Measures].[Sales from the last 2 Years]
AS Aggregate( Tail( [Date].[Calendar Year].[Calendar Year].Members, 2)
, [Measures].[Internet Sales Amount]
)
SELECT { [Measures].[Sales from the last 2 Years]
} ON COLUMNS
, { Tail( [Date].[Calendar Year].[Calendar Year].Members, 2)
} ON ROWS
FROM [Adventure Works]
Other interesting query, would be calculating a measure for the sum of each year and its previous:
WITH
MEMBER [Measures].[Sales from 2 years]
AS Aggregate( { [Date].[Calendar Year].CurrentMember.PrevMember
: [Date].[Calendar Year].CurrentMember }
, [Measures].[Internet Sales Amount]
)
SELECT { [Measures].[Internet Sales Amount]
, [Measures].[Sales from 2 years]
} ON COLUMNS
, NON EMPTY
{ [Date].[Calendar Year].[Calendar Year]
} ON ROWS
FROM [Adventure Works]
It does a sum, because the aggregation type of the measure [Measures].[Internet Sales Amount] is Sum, and the Aggregate function aggregates according to the measure's aggregation type.
Key Concepts in MDX
Aggregate function reference
MDX is a hard topic to grasp; if you're starting out, I recommend you read the book MDX Solutions, 2nd edition.