MDX Calculation speed - CurrentMember? - mdx

I am still getting to grips with MDX and I am looking for some help. Here is my MDX query:
CREATE MEMBER CURRENTCUBE.[Measures].[Fake]
AS
IIF(
(
(
[Sales Data].[Ship-to No].CurrentMember
,[Sales Data].[Price Type].&[Core]
,[Measures].[Sales - Local Currency]
)
/ (
[Sales Data].[Ship-to No].CurrentMember,
[Sales Data].[Price Type].[(All)].[ALL],
[Measures].[Sales - Local Currency]
)
) > 0.9
,1
,NULL
),
VISIBLE = 1;
CREATE MEMBER CURRENTCUBE.[Measures].[Test Calc]
AS
SUM(
Descendants(
[Sales Data].[Ship-to No].CurrentMember
,[Sales Data].[Ship-to No].[Ship-to No]
),
[Measures].[Fake]
),
VISIBLE = 1;
SalesData is the fact table and the basic calculation is to count the number of customers that have sales of more than 90% of the price type "Core".
The query currently takes around 5 seconds to complete but I think this can be faster if I don't use CurrentMember according to http://sqlblog.com/blogs/mosha/archive/2008/07/29/product-volatility-optimizing-mdx-with-mdx-studio.aspx
But I don't know where to begin in changing this, can anyone help me make this more efficient?

If you delete currentmember from the first measure does it make any difference?
CREATE MEMBER CURRENTCUBE.[Measures].[Fake]
AS
IIF(
(
(
[Sales Data].[Price Type].&[Core]
,[Measures].[Sales - Local Currency]
)
/ (
[Sales Data].[Price Type].[(All)].[ALL],
[Measures].[Sales - Local Currency]
)
) > 0.9
,1
,NULL
),
VISIBLE = 1;
In respect of the currentmember you use in the second measure maybe EXISTING will suffice:
CREATE MEMBER CURRENTCUBE.[Measures].[Test Calc]
AS
SUM(
EXISTING [Sales Data].[Ship-to No].[Ship-to No].MEMBERS
,[Measures].[Fake]
),
VISIBLE = 1;

Related

Convert sql rank to mdx rank

This is my sql code - I want to convert it into an mdx query.
Also those results set use into power bi report.
I am unable to write this sql query into mdx query. Can anybody help me?
Select * From(
Select
dense_RANK()over(partition by t.MonthName order by t.amount desc)rank
,t.*
From(
Select DSP.SalesPointShortName ,dd.MonthName
,SUM(fs.salesAmount)Amount
From FactSales FS
INNER JOIN DimDate dd on fs.DateKey=dd.DateKey
INNER JOIN DimSalesPoint DSP on DSP.SalesPointID=FS.SalesPointID
group by dsp.SalesPointShortName ,dd.MonthName
)as t
)as f where f.rank=1
My expected output is:
Lots of google searching i have the answer from below link
After following this link desire results comes.
https://bipassion.wordpress.com/2013/06/22/mdx-dense-rank/
`
WITH SET [Sorted Models] AS
// For each month get Top 25 records, choosed a Top 25 from business case
Generate (
[Dim Date].[Month Name].[Month Name].Members,
TopCount
( nonempty(
{
[Dim Date].[Month Name].CurrentMember
* [Dim Sales Point].[SalesPoint].[Sales Point Short Name].MEMBERS
}
,[Measures].[Sales Amount]
)
, 1
,[Measures].[Sales Amount]
)
)
//Select
//[Measures].[Sales Amount] on 0,[Sorted Models] on 1
//From [MdCubeTest]
//where [Dim Product Group Item].[Sub Category Name].&[Bag]
MEMBER [Measures].[Rank] AS
// Get the Rank of current member Tuple to Current Month Set
// Do not use Sorted Models set due to dynamic for each set
Rank (
(
[Dim Date].[Month Name].CurrentMember
, [Dim Sales Point].[SalesPoint].CurrentMember
)
, Generate ( [Dim Date].[Month Name].CurrentMember,
TopCount
( nonempty(
{ [Dim Date].[Month Name].CurrentMember
* [Dim Sales Point].[SalesPoint].[Sales Point Short Name]
}
,[Measures].[Sales Amount]
)
, 25
,[Measures].[Sales Amount]
)
)
, [Measures].[Sales Amount]
)
MEMBER [Measures].[Previous Set Index] AS
// Get the Set Index using Rank
(
[Measures].[Rank] - 2
)
MEMBER [Measures].[Dense Rank] AS
// Get the Dense Rank using the Index position value
CASE
WHEN [Measures].[Rank] = 1
THEN 1
ELSE
(
[Sorted Models].Item([Measures].[Previous Set Index]),
[Measures].[Dense Rank]
)
+
Iif
(
(
[Sorted Models].Item([Measures].[Previous Set Index]),
[Measures].[Sales Amount]
)
=
[Measures].[Sales Amount]
,0
,1
)
End
SELECT
{
[Measures].[Sales Amount]
, [Measures].[Rank]
, [Measures].[Dense Rank]
//, [Measures].[Previous Set Index]
} ON rows
,NON EMPTY
{
// FILTER Can be used to get the TOP 3 using DENSE RANK
FILTER (
[Sorted Models]
, [Measures].[Dense Rank] <=1
)
} ON columns
FROM [MdCubeTest]
where [Dim Product Group Item].[Sub Category Name].&[Bag]`

MDX SSAS Rank rownumber function

I have an existing SSRS report out of T-SQL query and I am trying to recreate it using MDX queries on SSAS cube. I am stuck with rewriting Row num and rank logic to MDX.
It is written as:
SELECT ceil((ROW_NUMBER() OVER (PARTITION BY PRODUCT ORDER BY YEARMONTH))/12)
Rank1 in the SQL. Can someone tell me if this can be done using MDX? In the cube, PRODUCT and YEARMONTH are coming from separate dimensions.
Thank you for your help!
There is the Rank() function. For example:
with
Dynamic Set OrderedSet as
Order(
NonEmptyCrossJoin(
[Date].[Year].[Year].Members,
[Product].[Product].[Product].Members,
[Measures].[Invoice Count],
2
),
[Measures].[Invoice Count],
BDESC
)
Member [Measures].[Rank] as
Rank(
([Client].[Client].Currentmember,[Date].[Year].CurrentMember),
OrderedSet
)
select {[Measures].[Invoice Count],[Measures].[Rank]} on 0,
non empty OrderedSet on 1
from [BI Fake]
where ([Date].[Day].&[20160120])
You can read in details about it from my blog post.
You can use Generate to repeat ranks like this:
WITH
SET [SalesRank] AS
Generate
(
[Customer].[Customer Geography].[State-Province]
,Order
(
NonEmpty
(
(
[Customer].[Customer Geography].CurrentMember
,[Product].[Product Categories].[Subcategory]
)
,{[Measures].[Internet Sales Amount]}
)
,[Measures].[Internet Sales Amount]
,BDESC
)
)
MEMBER [Measures].[CategoryRank] AS
Rank
(
(
[Customer].[Customer Geography].CurrentMember
,[Product].[Product Categories].CurrentMember
)
,Exists
(
[SalesRank]
,[Product].[Product Categories].CurrentMember
)
)
SELECT
{
[Measures].[Internet Sales Amount]
,[Measures].[CategoryRank]
} ON 0
,[SalesRank] ON 1
FROM [Adventure Works];
It results in this:

DAX - RANK Function

I have a RANK code from WEBI and need to write similar one in DAX or MDX.Both can work. But DAX will be more useful.
=Rank([OrderCount];([Category1];[Category2];[Category3]))
I have tried below code in DAX but it is not exact what i need.
=RANK.EQ(table1[OrderCount];table1[OrderCount])
Can you help me out write similar?
Grouping by Count. This is extra.
I'm not very good at DAX, but MDX way is the following:
with
Dynamic Set OrderedSet as
Order(
NonEmptyCrossJoin(
[Dim Product].[Subcategory Name].[Subcategory Name].Members,
[Dim Product].[Category Name].[Category Name].Members
[Measures].[Order Quantity],
2
),
[Measures].[Order Quantity],
BDESC
)
Member [Measures].[Rank] as
Rank(
([Dim Product].[Subcategory Name].Currentmember,
[Dim Product].[Category Name].Currentmember),
OrderedSet
)
select
{[Measures].[Order Quantity],[Measures].[Rank]} on 0,
non empty OrderedSet on 1
from
[Adventure Works DW2016CTP3]
DenseRank:
with
Dynamic Set OrderedSet as
Order(
NonEmptyCrossJoin(
[Dim Product].[Subcategory Name].[Subcategory Name].Members,
[Dim Product].[Category Name].[Category Name].Members,
[Measures].[Order Quantity],
2
),
[Measures].[Order Quantity],
BDESC
)
Dynamic Set DenseOrderedSet as
Order(
NonEmpty(
OrderedSet,
[Measures].[RankFirstMatch]
),
[Measures].[Order Quantity],
BDESC
)
Member [Measures].[Rank] as
Rank(
([Dim Product].[Subcategory Name].Currentmember,[Dim Product].[Category Name].CurrentMember),
OrderedSet
)
Member [Measures].[RankFirstMatch] as
IIF(
[Measures].[Order Quantity]
=
(
OrderedSet.Item([Measures].[Rank] -2),
[Measures].[Order Quantity]
),
NULL,
[Measures].[Rank]
)
Member [Measures].[RankDenseSet] as
Rank(
([Dim Product].[Subcategory Name].Currentmember,[Dim Product].[Category Name].CurrentMember),
DenseOrderedSet
)
Member [Measures].[DenseRank] as
IIF(
[Measures].[RankDenseSet] = 0,
(OrderedSet.Item([Measures].[Rank] -2),[Measures].[DenseRank]),
[Measures].[RankDenseSet]
)
select {[Measures].[Order Quantity],[Measures].[Rank],[Measures].[RankFirstMatch],[Measures].[RankDenseSet],[Measures].[DenseRank]} on 0,
non empty OrderedSet on 1
from [Adventure Works DW2016CTP3]
Here is the DAX measure for your question:
Rank =
IF (
HASONEVALUE ( YourTableName[ProductName] ),
RANKX (
ALL ( YourTableName ),
CALCULATE ( SUM ( YourTableName[Order Quantity] ) ),
,
,
DENSE
)
)
IF (HASONEVALUE ( YourTableName[ProductName] ).... part will eliminate your Grand Total from showing 1

Ranking of multiple dimensions, restarting for every year

I have a measure, Sales Amount. I want to rank customers within a divison by year for that measure. I need to also display that rank as a measure. The rank needs to start over every year. I am able to do customers by year and customers by division, but I can't seem to figure out how to combine them both so it iterates over both dimensions properly. Below is what I have for the customers by year. I have tried adding another Division set, creating another named set that I GENERATE with the YearsWithCustomers set, and RANK using that new named set. I seem to be super close to figuring this out but I think I am putting something in the wrong place. I got the idea to iterate over a set from one of Chris Webb's blogs, located here.
WITH
SET Years AS
TopPercent
(
[Sales and Forecast Date].[Calendar Year].[Year Number].MEMBERS
,100
,[Measures].[Sales Amount]
)
SET Customers AS
Filter
(
[Customer].[Customer Number].[Customer Number].MEMBERS
,
[Measures].[Sales Amount] > 0
)
SET YearsWithCustomers AS
Generate
(
Years
,Union
(
{[Sales and Forecast Date].[Calendar Year].CurrentMember}
,StrToSet
("
Intersect({},
{order(Customers,([Sales Amount],[Sales and Forecast Date].[Calendar Year].CurrentMember),desc)
as CustomerSet"
+
Cstr(Years.CurrentOrdinal)
+ "})"
)
)
,ALL
)
MEMBER [Measures].[Customer Rank] AS
Rank
(
[Customer].[Customer Number].CurrentMember
,StrToSet
("CustomerSet"
+
Cstr
(
Rank
(
[Sales and Forecast Date].[Calendar Year].CurrentMember
,Years
)
)
)
)
SELECT
{
[Customer Rank]
,[Measures].[Sales Amount]
} ON 0
,Order
(
Filter
(
(
YearsWithCustomers
,Customers
)
,
[Sales Amount] > 0
)
,[Sales Amount]
,desc
) ON 1
FROM [OrdersAndBudgets];
Here is what I currently have. I would expect to see 1, 2, 3, etc for the Rank measure. It should reset for each division for every year.
I like this sort of pattern:
WITH
SET [AllCountries] AS
[Country].[Country].MEMBERS
SET [AllProds] AS
[Product].[Product].[Product].MEMBERS
SET [Top5Prods] AS
Generate
(
[AllCountries] AS a
,{
(
a.CurrentMember
,[Product].[Product].[All]
)
+
//The top x prods
a.CurrentMember
*
TopCount
(
[AllProds]
,5
,[Measures].[Internet Sales Amount]
)
}
)
MEMBER [Product].[Product].[All].[Other Products] AS
Aggregate
(
[Country].CurrentMember * [Product].[Product].[Product].MEMBERS
-
[Top5Prods]
)
SELECT
{[Measures].[Internet Sales Amount]} ON COLUMNS
,Hierarchize(
{
[Top5Prods]
,[AllCountries] * [Product].[Product].[All].[Other Products]
}
) ON ROWS
FROM [Adventure Works];
It returns the following:
There is quite an extensive thread here: Top X of Top Y with RestOf member where X and Y are hierarchies from different dimensions

MDX calculated member filtration uses measure

I need help with calculated member
I have this code
CREATE MEMBER CURRENTCUBE.[Measures].[Summary distribution by CSKU]
AS count(
NONEMPTY(
crossjoin(
descendants ([05_Goods].[CSKU].currentmember,,LEAVES),
descendants ([04_Agents].[Agents hierarhy],,LEAVES)
)
)
),
FORMAT_STRING = "###,##0;-###,##0",
NON_EMPTY_BEHAVIOR = { [Quantity] },
VISIBLE = 1 , DISPLAY_FOLDER = 'Distribution' , ASSOCIATED_MEASURE_GROUP = '01_Sales' ;
but I want to see a result without elements where sum([Measures].[Sales amount]) <> 0
How can I do it?
Thanks!
Dmitry
I don't see other choice than using the MDX Filter function :
...
AS count(
FILTER(
crossjoin(
descendants ([05_Goods].[CSKU].currentmember,,LEAVES),
descendants ([04_Agents].[Agents hierarhy],,LEAVES)
)
, [Measures].[Sales amount] <> 0)
)
You might try adding the NonEmpty to the descendants method to improve performance (if some descendants have no [Sales Amount].