MDX formula for calculating All-Commodity Volume (%ACV) - ssas

I would like to create a measure for the All-Commodity Volume (ACV) indicator. The formula is the following :
Total Sales of Resellers Who Sold a Product / Total Sales of All Resellers
Let's take an example, for instance the product "LL Touring Frame - Blue, 44" from AdventureWorks2012DW Cube.
We can see it is sold by 14 resellers
These 14 resellers together make 2 706 909 $ of the sales
If I take all the resellers, they make 80 450 596 $ of the sales
My ACV measure would return 2 607 909 / 80 450 596 = 2% for the product "LL Touring Frame - Blue, 44", which means it present at the resellers who make 2% of my indirect sales.
What I'm looking for is the MDX expression which takes the "Reseller Sales Amount for all products" instead of the reseller sales amount for the selected product, but only if the "Reseller Sales Amount of the selected product is not null".
So far, thanks the help of the community I could make a query which gives me the correct result if I filter on some specific products :
WITH SET ActiveStores As NonEmpty(
[DimStore].[Store].[Store]
, { ([DimProduct].[Product].CurrentMember, [Measures].[Sales])}
)
MEMBER ACV AS SUM(ActiveStores, [Measures].[Store Sales]) / [Measures].[Store Sales]
SELECT NON EMPTY ACV ON COLUMNS,
NON EMPTY { ([DimProduct].[Product].[Product].ALLMEMBERS ) } ON ROWS
FROM ( SELECT ( { [DimProduct].[Product].&[ HAMAC DE VOYAGE] } ) ON COLUMNS FROM [Cube])
This query returns an ACV of 9% for the filtered product. However, if I remove the filter by putting only FROM [Cube], the ACV becomes 100% for all the products, even the one which was 9% with the previous query.
It is like the ActiveStores set is binded with the WHERE clause but not the ROWS Axis.
Regards

To find members where Sales is not null you can use the NonEmpty function:
NonEmpty(
[Stores].[Stores].members
,(
[Product].[Product].[ProductA]
, [Measures].[Sales]
)
)

What about:
Sum(
[Store].[Store].[Store].Members,
IIF(
IsEmpty([Measures].[Sales]),
Null,
(
ROOT([Product])
,ROOT([Supplier])
,ROOT([Promotion])
,ROOT([Misc])
,[Measures].[Sales]
)
)
)

I could find a solution this way :
I have added an aggregated fact (Store Sales) as an attribute of dimension Store. Created a Measure Store Sales out of it, then created a calculated measure with the following expression :
SUM(NonEmpty(
[DimStore].[Store].[Store]
,([Measures].[Sales])
), [Measures].[Store Sales]) / (ROOT([DimStore]), [Measures].[Store Sales])

Related

Why does my filter not work with calculated measures in Power BI, Power Pivot Excel?

I'm working with AdventureWorksDW2014. I created 2 measures, however they did not behave the way expected when i applied filter.
I have 2 tables FactInternetSales and DimCustomer. They are linked through CustomerKey.
I have 2 calculated measures. One measure (All Gender) sums up the Freight.
All Gender Freight = CALCULATE( sum(InternetSale[FactInternetSales.Freight]))
The other measure sums up the Freight of only Male
Male Measure Freight =
CALCULATE (
SUM ( InternetSale[FactInternetSales.Freight] ),
Customer[DimCustomer.Gender] = "M"
)
Now, if i use Power BI or Power Pivot Excel to view first Measure for all gender. I see this. Which is what i expected.
Gender All Gender
F 370341.79
M 363627.8142
For second measure, what i cannot explain is that i expect the total Freight for Female to be zero, since i did not include that in my Measure.
Gender All Gender
F 363627.8142 --Should be 0
M 363627.8142
You were missing FILTER function:
Male Measure Freight =
CALCULATE (
SUM ( InternetSale[FactInternetSales.Freight] ),
FILTER(Customer,Customer[DimCustomer.Gender] = "M")
)

Creating buckets by comparing Dimension member against Measure using MDX

I have a Product dimension with hierarchies - product_id, initial_price, product_name and Measures - units_sold, cost_per_unit, revenue_per_unit. For each product_id I need to compare initial_price against revenue_per_unit and then assign it to a bucket based on the comparison.
Consider the following example:
Input:
product_id initial_price revenue_per_unit
1 10 12
2 20 18
3 30 30
Output:
product_id bucket_name
1 Profit
2 Loss
3 Same
How can I achieve this using MDX?
WITH Member [Measures].[Bucket] AS
CASE
WHEN [Measures].[initial_price] < [Measures].[revenue_per_unit] THEN
"Profit"
WHEN [Measures].[initial_price] > [Measures].[revenue_per_unit] THEN
"Loss"
ELSE
"Same"
END
SELECT {[Measures].[Bucket]}
ON COLUMNS,
[Product].[Product Name].Members
ON ROWS
FROM [yourcube]
should deliver what you want. Please note that calculated measures need not return numbers, they also can return strings in MDX (they even can return a string for some cells, and a number for others).
In case you do not have the price available as e. g. an average price on aggregated product level, and want to do the bucketing on product level, the best solution would be not do do that in MDX at all, but in the cube design: Just calculate the bucket on the relational side, and add it as an attribute to the product dimension.
You did not state anything about other dimensions, especially time. In case some other dimensions matter as well to determine the bucket, it might be necessary to add a separate dimension just for the buckets.

MDX: Showing a zero count for non-existing members

I'm still a newbie at MDX, so maybe this will be a simple question.
I want to do something like see sales revenue by product: more specifically, products are classified in "classes" (where class can be A,B or C), so I want to see the amount of sales of class A products, class B and so on. If the Dimension "Product" has one Hierarchy "Classification" with level "Class", suppose the MDX query, for the sake of simplicity, is as follows:
SELECT
[Measures].[Sales] on COLUMNS,
[Product].[Classification].[Class].members on ROWS
FROM [Cube]
Problem is, if there's no record with class='C',for example, in Data table Product, there will be no member 'C', right? In that case, I'd like to show a zero count for that. So, instead of having:
| Sales
A 1000
B 200
I'd like:
| Sales
A 1000
B 200
C 0
Any help?
Thanks in advance!
Problem is, if there's no record with class='C',for example, in Data
table Product, there will be no member 'C', right?
As your select does not contain NON EMPTY ... ON ROWS, then 'C' should be returned with an empty cell as its 'Sales' value. It is possible that your 'client' tool is then ignoring it.
What you can do is define a calculated measure using the CoalesceEmpty() function to return a ZERO value instead of empty :
WITH
MEMBER [Measures].[Sales - X] as
CoalesceEmpty( ( [Measures].[Sales] ).Value, 0 )
SELECT
[Measures].[Sales - X] on COLUMNS,
[Product].[Classification].[Class].members on ROWS
FROM [Cube]

Fetching Previous Member while using order function in MDX

I have a mdx query which returns "productCode" and "Product share of total Sales" as a result.Also i need that query be sorted on "Product share of total Sales" (Decs)
So I came up with following MDX Query
WITH MEMBER [Measures].[Contribution] AS
Format(
IIF(
IsEmpty([Measures].[Detail_Net_Sales]),
0,
[Measures].[Detail_Net_Sales]
)/
[Measures].[SumTotalPayable]
)
SELECT
{[Measures].[Contribution]}
ON COLUMNS,
Order(
[DIMProduct].[ProductCode].[ProductCode].AllMEMBERS,
[Measures].[Contribution],
BDESC
)
ON ROWS
FROM [Model] }
the problem is when i also want to have Previous Contribution for each productcode
i wrote down somthing like this :
WITH MEMBER [Measures].[Contribution] AS
Format(iif(IsEmpty([Measures].[Detail_Net_Sales]),0,[Measures] [Detail_Net_Sales])/[Measures].[SumTotalPayable] )
MEMBER [Measures].[test]
AS
([Measures].[Contribution], [DIMProduct].[ProductCode].CurrentMember.PrevMember)
SELECT { [Measures].[Contribution] ,[Measures].[test]} ON COLUMNS
, Order([DIMProduct].[ProductCode].[ProductCode].AllMEMBERS ,[Measures]. [Contribution],BDESC)ON ROWS
FROM [Model]
but the above code will return previous Contribution without desire order.
do you have any idea how can i fix this?
Edit :
I want to have the Contribution of the previous row base on my sort and also have the test measure base on my prior sort,like the below table:
ProductCode Contribution Test
----------- ------------ ----
123 17.56 null
332 17.30 17.56
245 16 17.30
656 15.90 16
but what i get is like this :
ProductCode Contribution Test
----------- ------------ ----
123 17.56 17.30
332 17.30 16
245 16 Null
656 15.90 17.30
WITH MEMBER [Measures].[Contribution] AS
Format(
IIF(
IsEmpty([Measures].[Detail_Net_Sales]),
0,
[Measures].[Detail_Net_Sales]
)/
[Measures].[SumTotalPayable]
)
SET SortedProducts AS
Order(
[DIMProduct].[ProductCode].[ProductCode].AllMEMBERS,
[Measures].[Contribution],
BDESC
)
MEMBER [Measures].[PrevContribution] AS
(SortedProducts.Item(
Rank([DIMProduct].[ProductCode].CurrentMember, SortedProducts) - 2)
.Item(0),
[Measures].[Contribution])
SELECT
{[Measures].[Contribution], [Measures].[PrevContribution]}
ON COLUMNS,
SortedProducts
ON ROWS
FROM [Model] }
Your definition of the test measure uses the order of members as defined in the cube (alphabetically, if you did not define a custom order). But you need the order by Contribution, so I defined that as a named set containing the members in this order. Then I mis-used the Rank function which gives you the position of a tuple in a set. As the rank of the first member is 1, and I use the Item function to get a tuple within the set - which starts numbering the tuples with zero -, and we have to go one member back, you need the - 2, and finally, we need another Item(0) to get a member from the tuple.

MDX Balance to Totals

In the example below I have a products dimension with product id 1,2,3,4..etc. I want to create a calculated member called Balance To Totals that will sum over all the products they have chosen and subtract it from the grand total. This should happen over any measure they select. In the example below I have the products dimension on rows, and two measures on columns. If the user selects product 1,4,5 then the balance to totals will be the sum of those three products subtracted from the grand totals. Does anybody know how I can accomplish this through a calculated member?
Product Id Cost($) Profit($)
1 80 3
4 70 4
5 50 2
BalToTotal 125 25
Grand Total 325 34
I just set up a simple MDX query on AdventureWorks Cube, so you can play with it:
with set [SelectedProducts] as {[Product].[Subcategory].&[26], [Product].[Subcategory].&[1]}
member [Product].[Subcategory].[BalToTotal] as [Product].[Subcategory].defaultmember - Aggregate ([SelectedProducts])
select
{[Measures].[Internet Sales Amount], [Measures].[Reseller Order Quantity]} on 0,
{[SelectedProducts], [Product].[Subcategory].[BalToTotal], [Product].[Subcategory].defaultmember} on 1
from [Adventure Works]
The output will be:
Internet Sales Amount Reseller Order Quantity
Bike Racks €39.360,00 2.838
Mountain Bikes €9.952.759,56 23.351
BalToTotal €19.366.557,66 188.189
All Products €29.358.677,22 214.378
Hope this help