Slow SSAS cumulative sum calculated measure - ssas

I have a cumulative sum of a measure structured as:
Aggregate (
{ NULL : [Date].[Year - Month - Date].CurrentMember }
,[Measures].[Applications] )
From the date of the first application to the current date, the days of the date range must be contiguous.
The Date dimension however contains dates ranging from 1900-01-01 to well into the future.
I've attempted to eliminate dates before the first application, and future dates by structuring the calculated measure as follows:
CREATE MEMBER CURRENTCUBE.[Measures].[Applications TD] AS
CASE
WHEN
/* Eliminates dates before first applications, i.e. year 1900-01-01 */
Aggregate (
{ NULL : [Date].[Year - Month - Date].CurrentMember }
,[Measures].[Applications] ) < 0
THEN NULL
WHEN
/* Eliminates dates after today */
[Date].[Year - Month - Date].CurrentMember.MemberValue >= StrToMember('[Date].[Date].&['+Format(Now(),"yyyy-MM-ddT00:00:00")+']').MemberValue
THEN NULL
ELSE
Aggregate (
{ NULL : [Date].[Year - Month - Date].CurrentMember }
,[Measures].[Applications] )
END
I have been unsuccessful in any attempt to optimizing this by aggregating only where needed using a SCOPE as an alternative to the case statement, utilizing EXISTS and EXCEPT functions and many others.
When browsing the cube and dimensioning [Measures].[Applications TD] by [Date].[Year - Month - Date] user-defined hierarchy it is terribly slow.

IIF is generally faster than CASE, and SUM is often faster than AGGREGATE.
Although your main problem is the second part of your condition using membervalue - is it required or will the following not do the same thing? :
CREATE MEMBER CURRENTCUBE.[Measures].[Applications TD] AS
IIF(
SUM (
{ NULL : [Date].[Year - Month - Date].CurrentMember }
,[Measures].[Applications]
) < 0
, NULL
,
SUM (
{ NULL : [Date].[Year - Month - Date].CurrentMember }
,[Measures].[Applications]
)
)
I'd separate this out as a custom member:
CREATE MEMBER CURRENTCUBE.[Date].[Date].[All].[Today] AS //<< a little of syntax for this create
StrToMember('[Date].[Date].&['+Format(Now(),"yyyy-MM-ddT00:00:00")+']')
Then try a nested IIF:
CREATE MEMBER CURRENTCUBE.[Measures].[Applications TD] AS
IIF(
[Date].[Year - Month - Date].CurrentMember.MemberValue >= [Date].[Date].[All].[Today].MemberValue
, NULL
, IIF(
SUM (
{ NULL : [Date].[Year - Month - Date].CurrentMember }
,[Measures].[Applications]
) < 0
, NULL
,
SUM (
{ NULL : [Date].[Year - Month - Date].CurrentMember }
,[Measures].[Applications]
)
)
)
BUT
Rather than bothering with the "Today" member it will be a lot more efficient if you add an isToday column to DimDate - then have an attribute of the cubes date dimension using the column. That way you should be able to simplify this [Date].[Year - Month - Date].CurrentMember.MemberValue >= [Date].[Date].[All].[Today].MemberValue

Related

MDX calculation for 12 rolling months

I'm having issues trying to create a MDX calculated member inside a SSAS cube, that will show the aggregation for the previous 12 months (excluding the current month), based on a date from Calendar hierarchy.
I have found this post, however, because in my case the base measure is a DistinctCount aggregation, the YTD() function does not work by adding Aggregate() - it always displays NULL - and by adding Sum() it will display a RollingSum, which is incorrect.
This is against a DISTINCT COUNT measure and functions ok - although it is understandably slow:
WITH
MEMBER [Measures].[ytdCalc] AS
Aggregate
(
Head
(
Descendants
(
Ancestor
(
[Date].[Date - Calendar Month].CurrentMember
,[Date].[Date - Calendar Month].[Calendar Year]
).Item(0).Item(0)
,[Date].[Date - Calendar Month].[Calendar Month]
)
).Item(0).Item(0)
:
[Date].[Date - Calendar Month].CurrentMember
,[Measures].[Num People]
)
SELECT
{
[Measures].[ytdCalc]
,[Measures].[Num People]
} ON 0
,[Date].[Date - Calendar Month].[Calendar Month] ON 1
FROM [aCube];
YTD works fine for me. I have used it like this:
WITH
MEMBER [Measures].[ytdCalc] AS
Aggregate
(
YTD([Date].[Date - Calendar Month].CurrentMember)
,[Measures].[Num People]
)
SELECT
{
[Measures].[ytdCalc]
,[Measures].[Num People]
} ON 0
,[Date].[Date - Calendar Month].[Calendar Month] ON 1
FROM [aCube];

Return set of dates from hard-coded start point up to yesterday

I'd like to return the set of dates from the 18th of June up to yesterday. My attempt was as follows but I'm getting this error:
Executing the query ...
A calculated member cannot be used as an operand of the Range operator ( : ).
Execution complete
WITH
MEMBER [Date].[Date - Calendar Month].[LastDay] AS
Tail([Date].[Date - Calendar Month].[Calendar Day].members,1)
SET [Set_Dates] AS
{
[Date].[Date - Calendar Month].[Calendar Day].&[20130618]:
[Date].[Date - Calendar Month].[LastDay]
}
SELECT
NON EMPTY
[Set_Dates]
ON COLUMNS
FROM [myCube]
You might have to play about with the formatting and dimension/attribute names, but try this:
SELECT
NULL
ON COLUMNS,
{
[Date].[Full Date].[2013-07-01] :
STRTOMEMBER("[Date].[Full Date].[" + Format(DATEADD("d", -1, Now()),"yyyy-MM-dd") + "]", CONSTRAINED)
}
ON ROWS FROM [Cube]

MDX TTM Calculated member - day level

I need to create a calculated member that calculates revenue for TTM (Trailing Twelve Months) associated to selected date (day level).
I tried something like this:
SUM(
{
[Accounting Effective Date].[Date Hierarchy].CurrentMember.Lag(365)
: [Accounting Effective Date].[Date Hierarchy].CurrentMember
},
[Measures].[Revenue]
)
But this doesn't work with leap year, for example if I pick 2013-01-01 than it returns 2012-01-02.
I have also tried this but this one is also not good since it takes first day of the month:
SUM(
{
[Accounting Effective Date].[Date Hierarchy].CurrentMember.Parent.Lag(12).FirstChild
: [Accounting Effective Date].[Date Hierarchy].CurrentMember
},
[Measures].[Revenue]
)
Date hierarhy is following:
Year > Quarter > Month > Date
the following query can help, it uses cousin function to return last years date.
with member [Measures].[TestValue] as
(cousin([Date].[Calendar].currentmember,[Date].[Calendar].currentmember.parent.parent.lag(1)),[Measures].[Internet Sales Amount])
member [Measures].[TestDate] as
cousin([Date].[Calendar].currentmember,[Date].[Calendar].currentmember.parent.parent.lag(1)).item(0).name
select
{[Measures].[Internet Sales Amount],[Measures].[TestValue],[Measures].[TestDate]}
on columns,
{
[Date].[Calendar].[Date].&[20130922]
}
on rows from
[adventure works]

How to get the measure at specific day in that week using MDX

I am new to MDX,
I have a requirement, which is using the measure on that Saturday as the default of that week, I have a time dimension [CALENDAR],
but there are multiple hierachies, different hierachies have different week start, that means in [CALENDAR].[h1].[DATE], the week start may be Thursday(weekday in nature calendar), in the other may be Sunday(in nature calendar),
so I have to using [CALENDAR].[DATE], which is nature calendar, I can get the corresponding Saturday,
with member measures.[Weekday]
as datepart('w',[CALENDAR].[Fiscal].currentmember)
member measures.[SatDay]
as dateadd('d'
,7-datepart('w',[CALENDAR].[Fiscal].currentmember.MemberValue)
,[CALENDAR].[Fiscal].currentmember.MemberValue)
select
{
[Measures].[Plan Count]
,measures.[Weekday]
,measures.[SatDay]
} on 0,
[CALENDAR].[Fiscal].[Date] on 1
from [MyCube]
but how can I the measure on that day?
Try a sub-select using your date hierarchy containing week (Year-Week-Date).
with member [Measures].[WeekDate] as
dateadd('d' ,7 - datepart('w',[Dim Date].[Year - Week - Date].currentmember.MemberValue)
,[Dim Date].[Year - Week - Date].currentmember.MemberValue)
select {[Measures].[WeekDate], [Measures].[Plan Count]} on 0,
[Dim Date].[Year - Week - Date].Children on 1
from (
select ([Dim Date].[Year - Week - Date].[Week]) on 0
from [cube]
where (
//filters if necessary
)
)

MDX / Analysis Services Calculating Month To Date

I don't usually get involved with MDX if I dont have to, but....
I have a cube with simple fact table linked to a time dimension (with date,month,year columns and so on) and I want to be able for a given day of the month calculate the month to date total for that day.
In SQL it would be a doddle, however I'm not sure of how to achieve this in MDX.
Update I have an example working for a fixed date. Now I want to know how to do this for any possible date
WITH
MEMBER MTD_15_Feb_2010 AS
Aggregate
(
MTD([Date].[Year Name - Quarter Name - Month Name - Name].[Name].[02/15/2010]),
[Measures].[Value]
)
SELECT
{
MTD_15_Feb_2010
} ON 0
FROM [Cube]
You should be able to create the MDX using the MTD function. It will return the set of all days from the first of the month up to the member passed to the function.
Edit: There are multiple ways to update your example for any day. I would suggest replacing the date member [02/12/2010] with the CURRENTMEMBER function. This would also allow you to display the value for multiple dates as in the example below.
WITH MEMBER [MTD_Value] AS AGGREGATE (
MTD([Date].[Year Name - Quarter Name - Month Name - Name].[Name].CURRENTMEMBER)
, [Measures].[Value]
)
SELECT [MTD_Value] ON 0
, {
[Date].[Year Name - Quarter Name - Month Name - Name].[Name].[02/15/2010]
, [Date].[Year Name - Quarter Name - Month Name - Name].[Name].[01/15/2010]
, [Date].[Year Name - Quarter Name - Month Name - Name].[Name].[02/15/2009]
} ON 1
FROM [Cube]