Fetching Previous Member while using order function in MDX - ssas

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.

Related

MDX: Distinct Count of members summarized by another dimension

From my cube, I am trying to get a distinct count of all non-empty [ID].[FullID]s but summarized by [Underlying].
I know that, for example, there are two IDs for [Underlying].[Underlying1] at this particular WHERE slice and I can see this by running the below MDX query, which clearly gives me a row for each (but a zero count?):
Results:
Underlying | FullID | CountOf
------------------------------
Underlying1 | ID1 | 0
Underlying1 | ID2 | 0
...
Code:
WITH
MEMBER CountOf AS
DistinctCount([ID].[FullID].Children)
SELECT
NON EMPTY {[Underlying].Children * [ID].[FullID].Children
} ON ROWS,
NON EMPTY {CountOf
} ON COLUMNS
FROM [MyCube]
WHERE ([Time].&[2018-11-27T00:00:00],
[Factor].[FactorName].[FACTOR1],
[Factor].[FactorType].[FACTORTYPE1]
[Location].[Location1]
)
However when I remove the * [ID].[FullID].Children I don't get what would like:
What I want:
Underlying | CountOf
---------------------
Underlying1 | 2
...
What I get:
Underlying | CountOf
---------------------
Underlying1 | 24
...
There is clearly something else going on here to give me a 24 count, but I cannot figure it out...
You are getting 24 because you measure is counting the members in [ID].[FullID].Children. What i understand is that you want to count the number of [ID].[FullID] who have a fact value availabe against them for [Underlying].Children. So your code should be like this
WITH
MEMBER CountOf AS
Count(
nonempty(([Underlying].currentmember,[ID].[FullID].Children),
[Measures].[ConnectingMeasure])
)
SELECT NON EMPTY {[Underlying].Children } ON ROWS,
NON EMPTY {CountOf} ON COLUMNS
FROM [MyCube]
WHERE ([Time].&[2018-11-27T00:00:00],[Factor].[FactorName].[FACTOR1],
[Factor].[FactorType].[FACTORTYPE1],[Location].[Location1]
)
Here is a sample of what you want to do in adventureworks. I am trying to count all Promotion, that are present for a product based on the internet sales data.
WITH
MEMBER CountOf AS
count(nonempty( ([Product].[Product].currentmember, [Promotion].[Promotion].children) ,[Measures].[Internet Sales Amount]))
SELECT
NON EMPTY {CountOf} ON COLUMNS,
NON EMPTY {
([Product].[Product].Children )
} ON ROWS
FROM [Adventure Works]
//Base query to understand what is counted
WITH
MEMBER CountOf AS
Count(nonempty( ([Product].[Product].currentmember, [Promotion].[Promotion].children) ,[Measures].[Internet Sales Amount]))
SELECT
NON EMPTY [Measures].[Internet Sales Amount] ON COLUMNS,
NON EMPTY {
([Product].[Product].Children,[Promotion].[Promotion].children )
} ON ROWS
FROM [Adventure Works]

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

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

How to summarize on distinct values that group other values

I have this table:
Family_ID Person_ID Weight Spent_amount category
A 1 10 500 flight
A 2 10 500 flight
A 1 10 200 Hotel
A 2 10 200 Hotel
B 3 20 250 flight
B 3 20 300 Hotel
as we see here every family has a member and the costs per category calculated for the family not the person. And as we see not every family is equal to other but it has weight so every spent should be multiplied by family weight.
Now my goal is to write a measure for spent for every family
I wrote an equation but I see its very complex and I guess it give a wrong value. The Dax Equation I wrote is
cash_wieght:=SUMX (
SUMMARIZE (
s2g516_full,
s2g516_full[DIM_HOUSEHOLD_REF_ID],
"cash", CALCULATE ( MAXX ( SUMMARIZE (
s2g516_full,
s2g516_full[Persons],
s2g516_full[DIM_HOUSEHOLD_REF_ID] ,"cash1", CALCULATE ( Sum(s2g516_full[SPENT_PER_REASON])*MAX ( s2g516_full[Weight] ) )
/distinctcount(s2g516_full[person]) ),[Cash1] ) )
),
[cash]
)
When I took a sample by filtering with family_ID, it gave me the correct numbers for samples tests but maybe not of them. So how can I tell if I got the right results or not?
The result I want is the weight * spent_amount to be summed and filtered with family_ID as if person_ID is not in the table like: "if I filtered on Family_ID"
A 700*10
B 550 *20
First, DAX Formatter is your friend.
cash_wieght :=
SUMX (
SUMMARIZE (
s2g516_full,
s2g516_full[DIM_HOUSEHOLD_REF_ID],
"cash", CALCULATE (
MAXX (
SUMMARIZE (
s2g516_full,
s2g516_full[Persons],
s2g516_full[DIM_HOUSEHOLD_REF_ID],
"cash1", CALCULATE (
SUM ( s2g516_full[SPENT_PER_REASON] ) * MAX ( s2g516_full[Weight] )
)
/ DISTINCTCOUNT ( s2g516_full[person] )
),
[Cash1]
)
)
),
[cash]
)
After that, I think you've got the right intuition with SUMMARIZE(), but it can be much simpler than what you're doing. SUMMARIZE() groups by the fields in a table that you pass to it. Since members with the same [Family_ID] have the same values for [Spent_Amount] in a given [Category], all we need to do is group by everything from the table except [Person_ID].
cash_wieght:=
SUMX (
SUMMARIZE(
FactSpend
,FactSpend[Family_ID]
,FactSpend[Weight]
,FactSpend[Category]
,FactSpend[Spent_Amount]
)
,FactSpend[Weight] * FactSpend[Spent_Amount]
)
Here we use SUMMARIZE() to group by [Family_ID], [Weight], [Category], and [Spent_Amount]. Since addition and multiplication are commutative, it doesn't matter if we add first or multiply first.
So we use SUMX() to iterate over each row returned by our SUMMARIZE() and accumulate into a sum the values of [Weight] * [Spent_Amount] for each row in that grouped table.
Here's an image of my sample data and pivot table based on this measure performing appropriately. It also works when adding any of the attributes from the table to filter context. If one [Person_ID] is in context, the measure will return the value for the family, and at the family level will return the value for the family. We can alter the measure to only give a single [Person_ID]'s portion of the [Family_ID]'s whole if necessary.

MDX Using multiple date dimensions

What I want to do is generate a report containing an overview of gains and losses (of contracts). For example:
Year | contract_gains | contract_losses
_______________________________________
2015 | 10 | 2
2016 | 15 | 4
Showing the gains is quite easy because I can just count distinct contracts (which is the aggregator for the measure value) with a start period.
SELECT
{[contract_start_date].[year].MEMBERS}
ON ROWS,
{[Measures].[value]}
ON COLUMNS
FROM Cube
Showing the losses seperately is also easy because I can do the same with the second date dimension.
SELECT
{[contract_end_date].[year].MEMBERS}
ON ROWS,
{[Measures].[value]}
ON COLUMNS
FROM Cube
But what I want to do is generate a report containing both of the values in a single report. Sadly I have no idea how I can do this.
A little slow method, going cell by cell. Does this work for you -
WITH MEMBER [Measures].contract_losses AS
(
GENERATE
(
[contract_start_date].[year].CURRENTMEMBER,
FILTER
(
[contract_end_date].[year].MEMBERS,
CStr([contract_start_date].[year].CURRENTMEMBER.MEMBER_VALUE) = CStr([contract_end_date].[year].CURRENTMEMBER.MEMBER_VALUE)
)
).ITEM(0)
,
[Measures].[value]
)
MEMBER [Measures].contract_gains AS
[Measures].[value]
SELECT
NON EMPTY {[contract_start_date].[year].MEMBERS}
ON ROWS,
{[Measures].contract_gains, [Measures].contract_losses}
ON COLUMNS
FROM [Cube]

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]