How to get calculated measure to rollup correctly? - mdx

I have created a calculated measure that computes a weighted ratio for the current balance of all loans that fall into various risk ratings:
WITH
MEMBER [MEASURES].[Weighted Ratio] AS
(Measures.[Current Balance] * [Risk Rating].[Loan Rating Code].CurrentMember.member_value) /
(
[Measures].[Current Balance],
Ancestor([Risk Rating].[Loan Rating Code].CurrentMember, 1)
), FORMAT_STRING = "Standard"
SELECT
{[Measures].[Current Balance], [Measures].[Weighted Ratio]} on COLUMNS,
[Risk Rating].[Loan Rating Code].MEMBERS ON ROWS
FROM
[Test Cube]
The problem is that the results come back only at the child level, instead of being summed up:
Current Balance Weighted Ratio
All $3,245,749,329.46 (null)
0 $661,388.20 0.00
1 $17,341,801.10 0.01
2 $117,188,374.06 0.07
3 $596,477,812.37 0.55
4 $1,266,047,841.51 1.56
5 $986,789,425.72 1.52
6 $119,055,732.16 0.22
7 $133,050,242.69 0.29
8 $9,136,711.65 0.02
How can I get the sum to show up at the All level instead of (null)?

It looks like you didn't consider root member when you writing
Ancestor([Risk Rating].[Loan Rating Code].CurrentMember, 1)
When it comes to Root (All Level) above function try to find its ancestor and that's probably why you get null at that level. You should decide what to do when it comes to member "All Level" of [Risk Rating].[Loan Rating Code] dimension.
It looks like you just need to return a constant value "1" when it comes to the root level. If it is so, you should change your query as below;
WITH
MEMBER [MEASURES].[Weighted Ratio] AS
( Case
When [Risk Rating].[Loan Rating Code].CurrentMember.Level.Ordinal = 0
Then 1
Else (Measures.[Current Balance] * [Risk Rating].[Loan Rating Code].CurrentMember.member_value) /
(
[Measures].[Current Balance],
Ancestor([Risk Rating].[Loan Rating Code].CurrentMember, 1)
)
End
), FORMAT_STRING = "Standard"
SELECT
{[Measures].[Current Balance], [Measures].[Weighted Ratio]} on COLUMNS,
[Risk Rating].[Loan Rating Code].MEMBERS ON ROWS
FROM
[Test Cube]
If you want to return another result when it comes to root level just change the logic at the Then section.

I was able to get this to work using IsLeaf() and recursion in my calculated measure:
WITH
MEMBER [Measures].[Weighted Ratio] AS
IIF(
IsLeaf([Risk Rating].[Loan Rating Code].CurrentMember),
([Measures].[Current Balance] * [Risk Rating].[Loan Rating Code].CurrentMember.member_value) /
([Risk Rating].[Loan Rating Code].[All], [Measures].[Current Balance]),
SUM([Risk Rating].[Loan Rating Code].CurrentMember.Children, [Measures].[Weighted Ratio])
), FORMAT_STRING = "Standard"
SELECT
{[Measures].[Current Balance], [Measures].[Weighted Ratio]} on COLUMNS,
[Risk Rating].[Loan Rating Code].MEMBERS ON ROWS
FROM
[Test Cube]
Now the results look like I wanted:
Current Balance Weighted Ratio
All $3,245,749,329.46 4.24
0 $661,388.20 0.00
1 $17,341,801.10 0.01
2 $117,188,374.06 0.07
3 $596,477,812.37 0.55
4 $1,266,047,841.51 1.56
5 $986,789,425.72 1.52
6 $119,055,732.16 0.22
7 $133,050,242.69 0.29
8 $9,136,711.65 0.02

Related

Add column in existing MDX

I need to add a column in existing MDX and its values should be 1,1,1,1, and 2,2,2 like below.
Top line income 1
Products (GL) 1
Net Interest Income (NII) 1
Non Interest Revenue (NIR) 1
Products ( Non GL) 1
Net Interest Income (NII) 1
Non Interest Revenue (NIR) 1
WIP (No. of Prospects Logged) 2
WIP (Prospects Total Amount) Exposure 2
WIP (Prospects Total Amount) Deposits 2
Accepted Payouts in Progress (volume) 2
Accepted Payouts in Progress Exposure 2
Approval Rate (%) 2
Rejection Rate (Not taken up) (%) 2
...
...
How to achieve this in existing query?
MDX:
WITH
MEMBER [Measures].[Measure_Key] AS
[ScoreCardMeasures].[ScoreCard].Member_Key
MEMBER [Measures].[Measure_Group_Key] AS
[ScoreCardMeasures].[ScoreCard].Parent.Member_Key
MEMBER [Measures].[Structure_Level] AS
[CustomerStructure].[Provincial Structure].LEVEL_NUMBER
SET [ReportLevel] AS
Filter
(
[Report Levels].[Report Level].[Report Level]
,
Cint([Report Levels].[Report Level].Properties("Structure Level"))
=
Cint([Measures].[Structure_Level])
)
MEMBER [Measures].[Sequence] AS
[ScoreCardMeasures].[ScoreCard].Properties("Sequence")
MEMBER [Measures].[Indent] AS
[ScoreCardMeasures].[ScoreCard].Properties("Font Indent")
MEMBER [Measures].[Weight] AS
[ScoreCardMeasures].[ScoreCard].Properties("Font Weight")
MEMBER [Measures].[Header] AS
[ScoreCardMeasures].[ScoreCard].Properties("Values Header")
MEMBER [Measures].[Header1Caption] AS
[ScoreCardMeasures].[ScoreCard].Properties("Header Name1")
MEMBER [Measures].[Header2Caption] AS
[ScoreCardMeasures].[ScoreCard].Properties("Header Name2")
MEMBER [Measures].[Header3Caption] AS
[ScoreCardMeasures].[ScoreCard].Properties("Header Name3")
MEMBER [Measures].[Actual] AS
[Measures].[Measure Value]
MEMBER [Measures].[Target] AS
[Measures].[Measure Target]
MEMBER [Measures].[Average] AS
[Measures].[Average Value]
SELECT
{
[Measures].[Measure_Key]
,[Measures].[Measure_Group_Key]
,[Measures].[Structure_Level]
,[Measures].[Sequence]
,[Measures].[Indent]
,[Measures].[Weight]
,[Measures].[Header]
,[Measures].[Header1Caption]
,[Measures].[Header2Caption]
,[Measures].[Header3Caption]
,[Measures].[Actual]
,[Measures].[Target]
,[Measures].[Average]
} ON COLUMNS
,{
Filter
(
[ReportLevel]
*
Order
(
Descendants
(
StrToMember(#Financial_Measure)
,[ScoreCardMeasures].[ScoreCard].[Measure Code]
,LEAVES
)
,[Measures].[Sequence]
,ASC
)
,
[Measures].[Active Indicator] <> 0
)
} ON ROWS
FROM [ScoreCard]
WHERE
(
StrToMember(#SiteStructure)
,StrToMember(#Time)
);
I don't fully understand how you decide if it should be a 1 or a 2 - the question does not make it clear.
If you just want it hard-coded into the mdx then this might be an approach:
WITH
MEMBER [Measures].[Measure_Key] AS
[ScoreCardMeasures].[ScoreCard].Member_Key
MEMBER [Measures].[Measure_Group_Key] AS
[ScoreCardMeasures].[ScoreCard].Parent.Member_Key
MEMBER [Measures].[Structure_Level] AS
[CustomerStructure].[Provincial Structure].LEVEL_NUMBER
SET [ReportLevel] AS
Filter
(
[Report Levels].[Report Level].[Report Level]
,
Cint([Report Levels].[Report Level].Properties("Structure Level"))
=
Cint([Measures].[Structure_Level])
)
MEMBER [Measures].[Sequence] AS
[ScoreCardMeasures].[ScoreCard].Properties("Sequence")
MEMBER [Measures].[Indent] AS
[ScoreCardMeasures].[ScoreCard].Properties("Font Indent")
MEMBER [Measures].[Weight] AS
[ScoreCardMeasures].[ScoreCard].Properties("Font Weight")
MEMBER [Measures].[Header] AS
[ScoreCardMeasures].[ScoreCard].Properties("Values Header")
MEMBER [Measures].[Header1Caption] AS
[ScoreCardMeasures].[ScoreCard].Properties("Header Name1")
MEMBER [Measures].[Header2Caption] AS
[ScoreCardMeasures].[ScoreCard].Properties("Header Name2")
MEMBER [Measures].[Header3Caption] AS
[ScoreCardMeasures].[ScoreCard].Properties("Header Name3")
MEMBER [Measures].[Actual] AS
[Measures].[Measure Value]
MEMBER [Measures].[Target] AS
[Measures].[Measure Target]
MEMBER [Measures].[Average] AS
[Measures].[Average Value]
MEMBER [Measures].[1or2] AS
CASE
WHEN
[ScoreCardMeasures].[ScoreCard].CurrentMember
IS
[ScoreCardMeasures].[ScoreCard].[Measure Code].[Top Line Income]
THEN 1
WHEN
[ScoreCardMeasures].[ScoreCard].CurrentMember
IS
[ScoreCardMeasures].[ScoreCard].[Measure Code].[Products (GL)]
THEN 1
WHEN
[ScoreCardMeasures].[ScoreCard].CurrentMember
IS
[ScoreCardMeasures].[ScoreCard].[Measure Code].[WIP (No. of Prospects Logged)]
THEN 2
WHEN
[ScoreCardMeasures].[ScoreCard].CurrentMember
IS
[ScoreCardMeasures].[ScoreCard].[Measure Code].[WIP (Prospects Total Amount) Exposure]
THEN 2
END
SELECT
{
[Measures].[Measure_Key]
,[Measures].[Measure_Group_Key]
,[Measures].[Structure_Level]
,[Measures].[Sequence]
,[Measures].[Indent]
,[Measures].[Weight]
,[Measures].[Header]
,[Measures].[Header1Caption]
,[Measures].[Header2Caption]
,[Measures].[Header3Caption]
,[Measures].[Actual]
,[Measures].[Target]
,[Measures].[Average]
,[Measures].[1or2]
} ON COLUMNS
,{
Filter
(
[ReportLevel]
*
Order
(
Descendants
(
StrToMember(#Financial_Measure)
,[ScoreCardMeasures].[ScoreCard].[Measure Code]
,LEAVES
)
,[Measures].[Sequence]
,ASC
)
,
[Measures].[Active Indicator] <> 0
)
} ON ROWS
FROM [ScoreCard]
WHERE
(
StrToMember(#SiteStructure)
,StrToMember(#Time)
);

SQL subselect, group by, sum equivalent in MDX(SSAS)

I have a problem with creation of calculated member in SSAS.
Fact table:
Date Store Product Sales_in_USD
--------------------------------------------------
2016-07-01 Store1 Product1 50
2016-07-01 Store1 Product2 100
2016-07-01 Store2 Product3 70
2016-07-01 Store2 Product2 85
Dimensions:
Dates,Stores,Products
I want to get something like that:
If I filter by some product I want to get all sales by this store and date that include sales by filtered product+another products, for example I want filter by Product1:
SQL code:
select sum(Sales_in_USD)
from [Fact table]
where Store in (select Store from [Fact table] where Product="Product1")
Executing this sql code I get all Sales by Store1.
How I can create it with MDX when I want create a calculated member?
Output of calculated member must be the next:
Product Total_Sales_By_Store
------------------------------
Product1 50+100=150
Product2 50+100+70+85=305
Product3 70+85=155
1 - Determine the valid stores for the selected product.
NonEmpty(
[Store].[Store Name].MEMBERS,
([Product].[Product].Currentmember,[Measures].[Sales_in_USD])
)
2 - Once you have the stores for the current product, you want to calculate the sum of values for the possible tuples(cross join).
with member Measures.[Total Sum of Stores] as
sum(
[Product].[Product].Currentmember *
NonEmpty
(
[Store].[Store Name].MEMBERS,
([Product].[Product].Currentmember,[Measures].[Sales_in_USD])
)
,
[Measures].[Sales_in_USD]
)
select Measures.[Total Sum of Stores] on 0
from [YourCube]
where [Product].[Product].[Product1]
SELECT
[Measures].[Sales_in_USD] ON 0,
{[Store].[Store Name].MEMBERS,
[Product].[Product].MEMBERS} ON 1
FROM [Cube Name];
For your requirement, you really don't need a calculated member, since the measures will do the job for you
For Particular Product Name Product1, then
SELECT
[Measures].[Sales_in_USD] ON 0,
{[Product].[Product].&[Product1],
[Store].[Store Name].MEMBERS
} ON 1
FROM [Cube Name];
I think Sourav has pretty much nailed it but it could be more general?
WITH
MEMBER [Measures].[Total Sum of Stores] AS
SUM(
NONEMPTY(
[Store].[Store Name].MEMBERS,
(
[Product].[Product].Currentmember
,[Measures].[Sales_in_USD]
)
)
,[Measures].[Sales_in_USD]
)
SELECT
[Measures].[Total Sum of Stores] on 0,
[Product].[Product].[Product].MEMBERS ON 1
FROM [YourCube];

MDX Running total on every date member

I use the following MDX calculation to get the stock value per day:
SUM({NULL:[Date].[Calendar Hierarchy].CURRENTMEMBER} * [Measures].[Qty])
However this is giving me the following result
Date QtyOnHand
1/1/2015 10
4/1/2015 15
5/1/2015 16
Mark that the dates 2/1/2015 and 3/1/2015 are not shown, because there are no transactions on them.
I would like to get these shown to get the following result:
Date QtyOnHand
1/1/2015 10
2/1/2015 10
3/1/2015 10
4/1/2015 15
5/1/2015 16
How can I adjust my MDX statement to this?
Does IsEmpty help?
SUM(
{NULL:[Date].[Calendar Hierarchy].CURRENTMEMBER}
* IIF(
IsEmpty([Measures].[Qty])
,0
,[Measures].[Qty]
)
)
If it helps then it won't help performance.
I've tested the above and unsure why you do the cross-join inside the Sum - more standard is just to use the second argument.
This AdvWrks script is an example of your scenario i.e. there are gaps in the data:
SELECT
{[Measures].[Internet Sales Amount]} ON 0
,{
[Date].[Calendar].[Date].&[20050801]
:
[Date].[Calendar].[Date].&[20051201]
} ON 1
FROM [Adventure Works];
Here is the query using IsEmpty (with IIF):
WITH
MEMBER [Measures].[roll] AS
Sum
(
{[Date].[Calendar].[Date].&[20050801] : [Date].[Calendar].CurrentMember}
,IIF
(
IsEmpty([Measures].[Internet Sales Amount])
,0
,[Measures].[Internet Sales Amount]
)
)
SELECT
{[Measures].[Internet Sales Amount],[Measures].[roll]} ON 0
,{
[Date].[Calendar].[Date].&[20050801]
:
[Date].[Calendar].[Date].&[20051201]
} ON 1
FROM [Adventure Works];
Some of the results are the following:
So in your scenario I think this is very similar:
SUM(
{NULL:[Date].[Calendar Hierarchy].CURRENTMEMBER}
, IIF(
IsEmpty([Measures].[Qty])
,0
,[Measures].[Qty]
)
)

mdx topcount results not as expected

When I run the query below I only get 2 records back. If I drop the TOPCOUNT, I get 508 records.
Why is it not giving me the top 5 from the 508 records? What am I missing?
with
MEMBER Measures.[EmailCount] as IIF(ISEMPTY([Measures].[Tran Count]), 0 ,[Measures].[Tran Count])
MEMBER Measures.[IncomePerEmail] as
[Measures].[Amount]/ IIF(Measures.[EmailCount] = 0, 1 , Measures.[EmailCount] )
MEMBER Measures.[Income Range] as
CASE
WHEN Sum(EXISTING [Dim IFA Details].[Parent Key].[Adviser Group].Members,
Measures.[Amount] ) <= 10000 THEN '0-10000'
WHEN Sum(EXISTING [Dim IFA Details].[Parent Key].[Adviser Group].Members,
Measures.[Amount] ) <= 50000 THEN '10001-50000'
WHEN Sum(EXISTING [Dim IFA Details].[Parent Key].[Adviser Group].Members,
Measures.[Amount] ) <= 100000 THEN '50001-100000'
WHEN Sum(EXISTING [Dim IFA Details].[Parent Key].[Adviser Group].Members,
Measures.[Amount] ) <= 200000 THEN '100001-200000'
else '> 200000'
end
SELECT { [Measures].[Amount] , Measures.[EmailCount], measures.[Income Range], Measures.[IncomePerEmail] }
ON COLUMNS,
TOPCOUNT(
NONEMPTY([Dim IFA Details].[Parent Key].[Adviser Group].Members, Measures.Amount)
, 5
, Measures.[IncomePerEmail]
)
having Measures.[Income Range] = '10001-50000'
on rows
FROM [Income and Emails Cube]
where [Dim Date].[Fiscal Year].&[FY 13/14]
You have a HAVING clause which basically filters the set(of 5 records).
TOPCOUNTgets you 5 members but when the filtering happens, only two of the members meet the criteria Measures.[Income Range] = '10001-50000'
If you want to verify this, ORDER the query based on Measures.[IncomePerEmail] and see if the "top 5 records" have income ranges as '10001-50000'

MDX for Zero months in last 12 = Number of zero transacting months in the last 12 months rolling window

I am working on MDx query to count the number ZERO txn for each product for last 12 months from today's date. Prepared MDX query for Adventure works fine but my 2nd query running on my Acutal cube working correctly.
Can you please help me out to rectify the query or any filter needed to get correct results like 1st sample query?
1st Sample Query on Adventure Works: (working correctly)
WITH Member [Measures].[Months With Zero Sales] AS
COUNT(
FILTER(
DESCENDANTS(
{[Date].[Calendar].[Month].&[2008]&[1].LAG(12):[Date].[Calendar].[Month].&[2008]&[1]}, [Date].[Calendar].[Month]) ,
[Measures].[Sales Amount] = 0 ) )
SELECT {[Measures].[Months With Zero Sales]} ON 0,
[Product].[Product Model Lines].[Product Line].Members on 1
FROM [Adventure Works];
Product Lines Months With Zero Sales]
----------- -----------------
Accessory 0
Componenets 0
Mountain 0
Road 0
Touring 6
2nd Query on my Cube:
WITH Member [Measures].[Zero Months in last 12] AS
COUNT(
FILTER(
DESCENDANTS(
{[Settlement Date].[Calendar].[Settlement Calendar Month].&[2014]&[1].LAG(12):
[Settlement Date].[Calendar].[Settlement Calendar Month].&[2014]&[1]},
[Settlement Date].[Calendar].[Settlement Calendar Month]),
[Measures].[Transaction Count] = 0 ) )
SELECT {[Measures].[Transaction Count] ,[Measures].[Zero Months in last 12]} ON 0,
[Terminal].[terminal ID].members on 1
FROM [cubetxn]
I'm expecting if non zero where "transaction count" is (null), even if there is transaction count not null, there could be chances to have one month with empty tuples.
Can you please correct my query or someone can give me sample query which should able to give me total zero month txn count for last 12 month of each product.
Terminal ID Transaction Count Zero Months in last 12
---------- ----------------- -------------------------
All Terminals 504,112,053 0
Q1001 138,832 0
Q1002 (null) 0
Q1003 88,800 0
Q1004 (null) 0
First comment is that this is a quicker pattern to use when doing a count/filter:
WITH
MEMBER [Measures].[Months With Zero Sales] AS
Sum
(
Descendants
(
{
[Date].[Calendar].[Month].&[2008]&[1].Lag(12)
:
[Date].[Calendar].[Month].&[2008]&[1]
}
,[Date].[Calendar].[Month]
)
,IIF
(
[Measures].[Sales Amount] = 0
,1
,null
)
)
SELECT
{[Measures].[Months With Zero Sales]} ON 0
,[Product].[Product Model Lines].[Product Line].MEMBERS ON 1
FROM [Adventure Works];
Based on this more efficient approach does the following work?
WITH
MEMBER [Measures].[Zero Months in last 12] AS
Sum
(
Descendants
(
{
[Settlement Date].[Calendar].[Settlement Calendar Month].&[2014]&[1].Lag(12)
:
[Settlement Date].[Calendar].[Settlement Calendar Month].&[2014]&[1]
}
,[Settlement Date].[Calendar].[Settlement Calendar Month]
)
,IIF
(
[Measures].[Transaction Count] = 0
,1
,0
)
)
SELECT
{
[Measures].[Transaction Count]
,[Measures].[Zero Months in last 12]
} ON 0
,[Terminal].[terminal ID].MEMBERS ON 1
FROM [cubetxn];
If there is still a problem then why not reconstruct your script so you can manually check what to expect. So for the AdvWrks script I'd run this so that I could actually confirm that the 6 is correct:
SELECT
{[Measures].[Sales Amount]} ON 0
,
Descendants
(
{
[Date].[Calendar].[Month].&[2008]&[1].Lag(12)
:
[Date].[Calendar].[Month].&[2008]&[1]
}
,[Date].[Calendar].[Month]
)
*
[Product].[Product Model Lines].[Product Line].MEMBERS ON 1
FROM [Adventure Works];
So against your cube what does the following return?
SELECT
{[Measures].[Transaction Count]} ON 0
,
Descendants
(
{
[Settlement Date].[Calendar].[Settlement Calendar Month].&[2014]&[1].Lag(12)
:
[Settlement Date].[Calendar].[Settlement Calendar Month].&[2014]&[1]
}
,[Settlement Date].[Calendar].[Settlement Calendar Month]
)
*
[Terminal].[terminal ID].MEMBERS ON 1
FROM [cubetxn];
//Total Transactions count Weekend Sunday (i’ve date dimesion which holds day_in_week=’Sun’ for respective dates)
WITH SET AllTranSundays as
EXISTS(DATE.DATE.DATE.MEMBERS, DATE.DATE.day_in_week.&[Sun], "Sales")
//Count of all sundays which had transactions.
MEMBER Measures.CntAllTranSundays AS
COUNT(AllTranSundays)
//YTD Days = Count of days within calendar year to date
MEMBER Measures.CntDaysYTD as
COUNT(DESCENDANTS(ANCESTOR([DATE].[date].CURRENTMEMBER,
3), 3).item(0).item(0)
: [DATE].[date].CURRENTMEMBER)
//YTD Transactions = Transaction count year to date
MEMBER Measures.CntTranYTD as
COUNT(
EXISTS(
{DESCENDANTS(ANCESTOR([DATE].[date].CURRENTMEMBER,
3), 3).item(0).item(0)
: [DATE].[date].CURRENTMEMBER}, , "Sales"
)
//Zero months in last 12 = Number of zero transacting months in the last 12 months rolling window
MEMBER Measures.CntZeroTransactingMonths as
COUNT(
{ANCESTOR([DATE].[date].CURRENTMEMBER, 1).ITEM(0).LAG(12) : ANCESTOR([DATE].[date].CURRENTMEMBER, 1).ITEM(0)}
-
EXISTS({ANCESTOR([DATE].[date].CURRENTMEMBER, 1).ITEM(0).LAG(12) : ANCESTOR([DATE].[date].CURRENTMEMBER, 1).ITEM(0)}
, ,
"Sales")
)
//Consecutive zero months = Number of consecutive zero transacting months in last 12 months rolling window
Question Do you want a count of instances when consecutive months had zero transactions.
Or do you want a count of number of months which had consecutively no transactions?
What I am trying to say is say Jan, March, June, July, August, October, November had no transactions in the rolling last 12 months
As per case 1: the answer should be 2
As per case 2: the answer should be 5.
Will update my answer as per your clarification.
SELECT
{Measures.CntAllTranSundays, Measures.CntDaysYTD, Measures.CntTranYTD, Measures.CntZeroTransactingMonths} ON 0
FROM [YourCube]
where
[date].[date].[date].&[02/28/2015]