MDX LastPeriods for Rolling Count Null values - mdx

I have created a calculated member in my cube to figure out the event count for a 12 month rolling period. I have a measure called Event Count I have used the LastPeriods function to do this. However, I am having a problem when I have a month that has not got any data, my Measure [Event Count] is showing null and my calculated member shows null as well - I really need the 12 month rolling count to continue, replacing the Null for a 0 in the count so I would get a value for the month if I got a 0.
So if jan event Count was 5 and Feb was Null I should still all the previous 11 months worth of data added together with so the rolling count would still be 5
I have the following MDX as my calculated member and I still get nulls. I have tried doing a CASE statement as well.
IIF (isEmpty([Measures].[Event Count]) ,
Sum(LastPeriods(12,[Event Date].[CalendarYQMD].CurrentMember),0),
Sum(LastPeriods(12,[Event Date].[CalendarYQMD].CurrentMember),[Measures].[Event Count])
has anyone came across this problem before or can see where I am going wrong

Firstly, you explicitly state in your expression that the result should be zero and not the event count if the current period has no event count, as then you sum 0 and not the event count measure. hence, the formula should be
Sum(LastPeriods(12,[Event Date].[CalendarYQMD].CurrentMember),[Measures].[Event Count])
without the IIf(IsEmpty()).
You could then set the value to zero after summing, by nesting the result into CoalesceEmpty(), i. e.
CoalesceEmpty(
Sum(
LastPeriods(12,[Event Date].[CalendarYQMD].CurrentMember),
[Measures].[Event Count]
),
0
)
Secondly, the formula as stated only works correctly for months. For quarters, it would sum 12 quarters, and for years it would sum twelve years. Instead of using LastPeriods, I would suggest using ParallelPeriod to go back one year, independent of the level of teh period hierarchy on which you are, and then from there go one member forward to get the start period of the sum, i. e. use the following formula:
CoalesceEmpty(
Sum(
ParallelPeriod(
[Event Date].[CalendarYQMD].[Year Name],
1,
[Event Date].[CalendarYQMD].CurrentMember
).NextMember
:
[Event Date].[CalendarYQMD].CurrentMember,
[Measures].[Event Count]
),
0
)
Please note that the colon operator creates a range of members beginning with its left operand and ending with its right operand.

Related

MDX SSAS query issue with Linkmember and filter 2 date timensions

I need to compute the aggregate of Opportunities Count that are active at a time (which is defined by period between start date and closing date) Not just for that period but for over all...
Opportunities Count for 2016 should include the sum of opportunities from NULL : 2015 and those that are closed in 2016:NULL.
Same thing for month and year
I have the following query that works but is giving me incorrect results for quarter, Month, date level. But gives the correct results for Year. I guess it is because of non unique key names in both dimensions
with member [Measures].[cumulative_count]
as
aggregate({NULL:[Time Dimension].[Year-Qtr-Month-Date].currentmember.lag(1) } *
{LINKMEMBER([Time Dimension].[Year-Qtr-Month-Date].currentmember.lead(1),[Opportuntity Close Dt].[Year-Qtr-Month-Date]):NULL}
,[Measures].[Opportunities Count])
SELECT [Measures].[cumulative_count] on columns,
[Time Dimension].[Year-Qtr-Month-Date].[Month].members on rows
from
AdventCube
I guess I am running into an issue with ALL member as specified in the link
http://richardlees.blogspot.com/2011/06/linkmember.html
But to override the ALL member I am running into syntax errors. Could anyone please help?

AVG(EXISTING()) syntax error

I want to calculate sales for promotion using it's date. I need 3 measures, avg sales from 21 days before promotion start date, sales in between of promotion's start and end date, and sales from 21 days after promotion's end date.
Why Visual Studio highlights avg in code below?
CREATE MEMBER CURRENTCUBE.[Measures].[Sales in promotion]
AS Avg(Existing([Promotion].[Promotion name].[Promotion name]),[Measures].[Sales]), ...
Same in here:
CREATE MEMBER CURRENTCUBE.[Measures].[Sales before promotion]
AS (EXISTING([Promotion].[Promotion name].[Promotion name]), AVG(strtomember("[Date].[Date].&["+ [Promotion].[Date].currentmember.member_key+"]").lag(21) : strtomember("[Date].[Date].&["+ [Promotion].[Date From].currentmember.member_key+"]"),
[Measures].[Sales])) ...
If I do sum(existing()) in first measure, the sum is calculated correctly, but it doesn't allow me to get average.
EXISTING will only help if [Promotion] is part of your query in either the WHERE or SELECT clause. If it is not included in either of these clause then EXISTING will be finding 1 member - the All member.
You could try NonEmpty and maybe move the period logic into a custom set?
WITH
SET [PERIOD] AS
STRTOSET(
"[Date].[Date].&["+ [Promotion].[Date].currentmember.member_key+"].lag(21)
:
[Date].[Date].&["+ [Promotion].[Date From].currentmember.member_key+"]"
)
From the code you posted I cannot tell if you want a daily average or and average per promotion ? Say there were 2 promotions over the 21 days does this mean you want (Total/2/21) ?

Count maximum sequel of null values - mdx query

I want to create a member based on this problem
I have a Product A being sold
I want to find the largest range of consecutive days without sale
example:
days 1,2,3 the product not sale, after that,it sold for 15 consecutive days, at 19th day it didnt sell for 2 days and after that it sold every day until the end of the month
so my maximum days without sale was 3
The following query delivers in the Microsoft sample cube Adventure Works what you want:
WITH Member Measures.[days without sales] AS
IIf( [Measures].[Internet Sales Amount] > 0
, 0
,(Measures.[days without sales], [Date].[Calendar].CurrentMember.PrevMember) + 1
)
Member Measures.[Max days without sales] AS
Max( [Date].[Calendar].[Date].Members
,Measures.[days without sales]
)
SELECT { [Measures].[Max days without sales] }
ON COLUMNS
FROM [Adventure Works]
WHERE [Product].[Product].&[486]
The measure days without sales is defined recursively, and returns how many days up to and including the current member of the [Date].[Calendar] hierarchy there was no sales. You may need to adapt the criteria for "without sale", bearing in mind that in MDX, numerical comparisons treat NULL as 0 - which is different from SQL.
This measure only works correctly if there is a member in this hierarchy for each day, i. e. there are no gaps in this hierarchy. And actually, the definition is more general than just working for days: If you use months for the [Date].[Calendar].CurrentMember, it would give you the number of months without sales, etc. It works with each level of the hierarchy.
The measure Max days without sales does not contain the product in its definition, it delivers the maximum days for whatever is in context (in this case the product in the WHERE clause).
Please note that - as actually there is a loop over all days in the [Date].[Calendar] hierarchy when calculating Measures.[Max days without sales], and within that the recursion again iterates along the previous days, and all this for each cell in the result set - this may be slow for large reports.

MDX: Limit parent aggregate by child value

My MDX is fledgling at best, and it is a realistic possibility that I don't even know how to phrase my question correctly to search for an answer. Sorry if this is a duplicate.
I have a date/time hierarchy [Dates]:
[Work Date].[Dates].[Year].[Quarter].[Month].[Day]
What I want to do is return the previous 5 years worth of data, for the month of X (let's assume January):
Year Sub Total
2008 645712.11
2009 848075.43
2010 765802.60
However, I'm having trouble restricting the "Year" data, based on the specific month. I have tried this MDX code, but it yields no results at all:
SELECT [Measures].[Sub Total] ON 0,
[Work Date].[Dates].[Year] ON 1
FROM (
SELECT [Work Date].[Dates].[Month].&[01] ON 0
FROM [Data Warehouse])
If I edit the sub-select I can get a specific year, quarter and month... but I only want to restrict the month portion and not the year. I've looked into using an EXCEPT clause, but I run into the same issue. Does that make any sense? I appreciate any help, and am not opposed to reading long articles if it will further my learning / understanding. Thanks!
After your explanation in comments: To get the same child of each hierarchy level you can use the MDX function COUSIN (here the reference on msdn). As documentation said:
Returns the child member with the same relative position under a
parent member as the specified child member.
so in your case your Date dimension has to be complete without missing months or days, so you can write a query like this (I've tested on AdventureWorks)
with member [Measures].[Sub Total]
as (Cousin([Date].[Calendar].[Month].&[2004]&[1], [Date].[Calendar].CurrentMember), [Measures].[Internet Sales Amount]) , Format_string = 'Currency'
Select {[Measures].[Internet Sales Amount],[Measures].[Sub Total] } on 0
,{
[Date].[Calendar].[Calendar Year].&[2002]
,[Date].[Calendar].[Calendar Year].&[2003]
,[Date].[Calendar].[Calendar Year].&[2004]
} on 1
from [Adventure Works]
I've put side by side the total and the sub total for the years. I am considering only these 3 years because they are complete from jan to dec and I can apply cousin operator without problem.
Hope this help!

Filtering a Dimension Relative to a CurrentMember in MDX

I'm having a bit of trouble accomplishing something that I think should be relatively straightforward in MDX. I would like to create a calculated member that provides a sum of one of my measures over the previous two weeks at a given point in time. My time dimension looks like:
TimeId TradingDate Day of Week
-----------------------------------
1000 11/1/2012 Thursday
1001 11/2/2012 Friday
1002 11/5/2012 Monday
1003 11/6/2012 Tuesday
... ...
What makes this particularly difficult is that my Time dimension is not quite complete. The members of my Time dimension only correspond to trading days in the stock market, and not all time. This means that weekends, holidays, or any other day in which the stock market is closed are excluded. This also means the normal methods of traversing time such as LAG or PARALLELPERIOD will not work quite right here. LAG(14), for example, means "14 trading days", which at any given point could represent a variable length of actual time.
Inside my calculated member, I'm attempting to use FILTER in order to get only time members that are within the previous two weeks of the CurrentMember. However, I can't seem to figure out the proper syntax (if there is one) to accomplish this. I imagine it would be something like:
WITH MEMBER [Sum of Price Previous 2 Weeks] AS
SUM(
FILTER(
[Time].[TimeId].Children
, [Time].[TradingDate].MemberValue
>= VBA!DATEADD("ww", -2, [Time].[TradingDate].CurrentMember.MemberValue)
)
, [Price]
)
However, this doesn't quite work. I can't seem to separate the context of the calculated members current iteration from what would be a separate context inside of the FILTER function. In other words, I'm not sure how to say:
"When iterating over the set inside of FILTER, compare the current
member of each iteration against the value of the CurrentMember in
the scope of the calculated member"
Is what I'm trying to accomplish even possible? Is there a different approach I could be taking to accomplish what I'm after?
The result you'll get from a calculated member will depend on the axis of your query. So first, make sure you have [Time].[TradingDate] in your axis.
Second, your [Time].[TradingDate] hierarchy should be ordered by Key (I assume TradingDate is the key).
Now you can use this member definition:
WITH MEMBER [Sum of Price Previous 2 Weeks] AS
SUM(
[Time].[TradingDate].CurrentMember.Lag(14):[Time].[TradingDate].CurrentMember, [Price]
)
You can use set aliases to refer to the outer CurrentMember in the Filter context:
WITH MEMBER [Sum of Price Previous 2 Weeks] AS
SUM(
GENERATE([Time].[TradingDate].CurrentMember AS CurrentDateAlias,
FILTER(
[Time].[TimeId].Children
, [Time].[TradingDate].MemberValue
>= VBA!DATEADD("ww", -2, CurrentDateAlias.Item(0).MemberValue)
)
)
, [Price]
)
GENERATE is used just to define the alias somewhere.