MDX. Mixing measures with dimensions - ssas

Have multiple departments, which have monthly sales' measure and "Inception to Date" (ITD) and "Year to Date" (YTD) sales' data measures.
SELECT {[Dep1], [Dep1ITD], [Dep1YTD], [Dep2], [Dep2ITD], [Dep2YTD]} ON ROWS,
{[Calendar Date].[Calendar yyyy-MMM].[Calendar yyyy-MMM].ALLMEMBERS} ON COLUMNS
FROM (
SELECT ( { [Calendar Date].[Calendar yyyy-MMM].&[202206]:[Calendar Date].[Calendar yyyy-MMM].&[202209]}
) ON COLUMNS
FROM [MyCube])
Code above produces following result:
I do not have a need to show all YTD & ITD data, I need to show it only once - before the beginning of the period. Like this:
YTD & ITD are calculated from the May-2022 numbers minus May's sales.
In this example:
"Dep1 ITD": 538 = 543 - 5
"Dep2 ITD": 288 = 292 - 4
"Dep1 YTD": 23 = 28 - 5
"Dep2 YTD": 14 = 18 - 4
Is it possible to do with MDX?
If so, how complicated it would be?
Will it be faster than extract two separate data sets and link them in a front-end application?

Related

How to merge two MDX query results having different measures and filters?

Let's start by saying that I'm a total newbie on MDX, I need to merge two (or more) query results into one pivot.
The queries will have the same dimensions on ROWS and COLUMNS, but different measures and filters (normally a time period).
Here is an example
Query 1:
SELECT
NON EMPTY {{[stores].[storecountry].[storecountry].Members}} ON COLUMNS,
NON EMPTY {{[SalesTypes].[Description].[Description].Members}} *
{[Measures].[TransactionValue], [Measures].[TransQty]} ON ROWS
FROM [Model]
WHERE ({[dDates].[Date].[Date].&[2016-01-05T00:00:00] : [dDates].[Date].[Date].&[2016-01-12T00:00:00]})
Result of query 1:
CA US
Regular Sale TransactionValue 761 16
Regular Sale TransQty 8 233
Return TransactionValue 156 4
Return TransQty 1 45
Query 2:
SELECT
NON EMPTY {{[stores].[storecountry].[storecountry].Members}} ON COLUMNS,
NON EMPTY {{[SalesTypes].[Description].[Description].Members}} *
{[Measures].[DiscountPerc]} ON ROWS
FROM [Model]
WHERE ({[dDates].[Date].[Date].&[2015-03-12T00:00:00] : [dDates].[Date].[Date].&[2015-06-02T00:00:00]})
Result of query 2:
CA US
Regular Sale DiscountPerc 40 % 59 %
Return DiscountPerc 32 % 43 %
Expected result after merging
CA US
Regular Sale TransactionValue 761 16
Regular Sale TransQty 8 233
Regular Sale DiscountPerc 40 % 59 %
Return TransactionValue 156 4
Return TransQty 1 45
Return DiscountPerc 32 % 43 %
Is it achievable without manually merging the AdomdClient.CellSet from the calling application?
Thank you!
I'd use calculated members:
with
Member [Measures].[TransactionValueReport] as
Aggregate(
{[dDates].[Date].[Date].&[2016-01-05T00:00:00]:[dDates].[Date].[Date].&[2016-01-12T00:00:00]},
[Measures].[TransactionValue]
)
Member [Measures].[TransQtyReport] as
Aggregate(
{[dDates].[Date].[Date].&[2016-01-05T00:00:00]:[dDates].[Date].[Date].&[2016-01-12T00:00:00]},
[Measures].[TransQty]
)
Member [Measures].[DiscountPercReport] as
Aggregate(
{[dDates].[Date].[Date].&[2015-03-12T00:00:00]:[dDates].[Date].[Date].&[2015-06-02T00:00:00]},
[Measures].[DiscountPerc]
)
Select
Non Empty [stores].[storecountry].[storecountry].Members on 0,
Non Empty [SalesTypes].[Description].[Description].Members * {[Measures].[TransactionValueReport],[Measures].[TransQtyReport],[Measures].[DiscountPercReport]} on 1
From [Model]

MDX script - mix empty and non empty on the same axis

I would like to ask your help to understand the main logic of MDX query. I would like to query different dimensions from the cube. But: in some case I would like to hide the NULL values, but in other dimension it is still needed. In my case I would like to provide date weeks and it dates for every day within the time period. (Even if it has no data) The content would be order number, position number and company and of course the KPI: OTD_customer. I tried many times to fix the null value issue, but I'm beginner on MDX. I tried to use NON EMPTY keyword and also Nonempty function, but still don't have the wished result. One more complicated thing is to filter the date for time period: based on actual day the last 15 weeks. (this part is working fine)
> SELECT NON EMPTY
> { [OTD_customer_new] } ON COLUMNS, NON EMPTY
> {
> (
> (( strtoset("LASTPERIODS(15,([Date - Plan Delivery Date].[Calendar Week].&[" + left(ltrim("2017 KW 10"),4) +" KW " + right(ltrim("2017 KW 10"),2) + "]) ) ")
> , [Order Number].[Order Number].[Order Number].ALLMEMBERS
> , [Position Number].[Position Number].[Position Number].ALLMEMBERS
> ,[Date - Plan Delivery Date].[Day of the Week].ALLMEMBERS
> ,[Group Structure].[Group Structure].ALLMEMBERS
> ) )
> *
> ([Date - Plan Delivery Date].[Date].[All].FirstChild:
> tail
> ( filter
> ( [Date - Plan Delivery Date].[Date].[All].Children,
> [Date - Plan Delivery Date].[Date].CurrentMember.Name <= Format(Now(), "yyyyMMdd")
> ), 1
> ).item(0)
> ))
> }
> ON ROWS
> FROM [ProductionCube]
Shall I use the filter in where condition? what is the best way to query the result from the cube? When it will be in normal relation database I would use a simple joins for this purpose.. But here in MDX I don't see the possibility with left and inner joins in script. Based on my understanding the hole axis may have the possibility to filter the null values. Do you have any idea? (thank you for reading) Current result example can be found here
The Non Empty function designed to filter empty axes (when your output is calculated). The NonEmpty function does the calculation of set. So, if you run:
Non Empty {Set1} * {Set2}
You'll get only crossjoined non-empty records.
If you run:
NonEmpty({Set1} * {Set2}, [Measures].[NonEmptyMeasure])
You'll get the same result, but the mechanic is a bit different. If you want to filter only specific sets you may use NonEmpty around these sets:
{Set1} * NonEmpty({Set2}, [Measures].[NonEmptyMeasure])
Set1 won't be filtered. Nonetheless, all members of Set1 will crossjoined with all non-empty members of Set2. Most likely that's not what you want.
You have many extra attributes joined to your date. What do expect them to return for empty records? I may guess you want to return All member, say, Set1 is a date set and Set2 is a company set:
NonEmpty({Set1} * {Set2}, [Measures].[NonEmptyMeasure]) + { {Set1} - NonEmpty({Set1}, [Measures].[NonEmptyMeasure])} * {Set2}.Item(0).Parent
Explanation:
1. NonEmpty({Set1} * {Set2}, [Measures].[NonEmptyMeasure]) -- returns non-empty records
2. {Set1} - NonEmpty({Set1}, [Measures].[NonEmptyMeasure]) -- returns empty dates
3. {Set2}.Item(0).Parent -- returns All member
The result will look like the following:
|=====================================|
| 2016 week 51 | Company1 | 1 |
| 2016 week 51 | Company2 | 1 |
| 2016 week 51 | Company3 | 1 |
| 2016 week 52 | All companies | NULL |
=======================================
Is it the wished result?

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

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