MDX: Moving average calculation only gives (null) results - ssas

I am trying to compute a moving average using MDX in SSAS 2014,but all results come out (null).
Reading multiple web references and blog posts makes me think that this should work, giving a 3-month moving average:
With
MEMBER [Measures].[MA3] AS
Avg(
[Date].[Calendar Years].[Month].CurrentMember.Lag(2)
: [Date].[Calendar Years].[Month],
[Measures].[Project Views]
)
SELECT { [Measures].[Project Views], [Measures].[MA3] } ON 0,
[Date].[Calendar Years].[Month] ON 1
FROM [ProjectAccesses]
However, (null) appears in each column.
I'd expect the count of members to be 3 in every case using:
MEMBER [Measures].[C3] AS
Count(
[Date].[Calendar Years].[Month].CurrentMember.Lag(2)
: [Date].[Calendar Years].[Month],
INCLUDEEMPTY
)
but again, no syntax error is detected but all values are (null), leading me to believe that maybe the month-range sets are empty.
I've been around and around this for hours now and have run out of things to try.
Can anyone suggest what might be going wrong please; I'm a newcomer to MDX so it's possible that my query is wrongly structured or there is some error in my cube configuration that I have not been able to find.
Thanks

I believe you need to change
": [Date].[Calendar Years].[Month],"
To
": [Date].[Calendar Years].currentmember,"
[Date].[Calendar Years].[Month] -> should give the level, not the current member which is what you want

I'm surprised that you cannot use the Calendar Years hierarchy throughout. I've added a couple of extra diagnostic measures so you can see what the currentmember function is returning:
WITH
MEMBER [Measures].[MA3] AS
AVG(
[Date].[Calendar Years].CurrentMember.Lag(2)
: [Date].[Calendar Years].CurrentMember,
[Measures].[Project Views]
)
MEMBER [Measures].[C3] AS
COUNT(
[Date].[Calendar Years].CurrentMember.Lag(2)
: [Date].[Calendar Years].CurrentMember,
INCLUDEEMPTY
)
MEMBER [Measures].[Diagn1] AS
[Date].[Calendar Years].CurrentMember.member_caption
MEMBER [Measures].[Diagn2] AS
[Date].[Calendar Years].CurrentMember.Lag(2).member_caption
SELECT
{
[Measures].[Project Views]
, [Measures].[MA3]
, [Measures].[C3]
, [Measures].[Diagn1]
, [Measures].[Diagn2]
} ON 0,
[Date].[Calendar Years].[Month].MEMBERS ON 1
FROM [ProjectAccesses];

I found the solution. I had assumed that i would need to form my set based on a member within my [Calendar Years] hierarchy. However the following, without the hierarchy, works fine (although I can't explain why the original version did not).
With
MEMBER [Measures].[MA3] AS
Avg(
[Date].[Month].CurrentMember.Lag(2)
: [Date].[Month].CurrentMember,
[Measures].[Project Views]
)
MEMBER [Measures].[C3] AS
Count(
[Date].[Month].CurrentMember.Lag(2)
: [Date].[Month].CurrentMember,
INCLUDEEMPTY
)
SELECT { [Measures].[Project Views], [Measures].[MA3] , [Measures].[C3] } ON 0,
[Date].[Calendar Years].[Month] ON 1
FROM [ProjectAccesses]

Related

AdventureWorks date dimension shows different results depending on selected hierarchy

Here are two simple queries which shows data on month level filtered by dates.
In the first query I am using Month level of "Date.Calendar" user hierarchy.
SELECT
NON EMPTY { [Measures].[Internet Sales Amount] } ON 0,
NON EMPTY { [Date].[Calendar].[Month].&[2013]&[1] } ON 1
FROM [Adventure Works]
WHERE {[Date].[Date].&[20130105]:[Date].[Date].&[20130106]}
And recieved - January 2013 -> $857,689.91
Results
In the second query I am using "Date.Month of Year" attribute hierarchy.
SELECT
NON EMPTY { [Measures].[Internet Sales Amount]} ON 0,
NON EMPTY { [Date].[Month of Year].&[1] } ON 1
FROM [Adventure Works]
WHERE { [Date].[Date].&[20130105] : [Date].[Date].&[20130106] }
And received - January -> $54,468.46
Results
I can not figure out why these two queries show different results. If the same dimension is used and data are filtered/sliced on the lovest possible level.
Here are values for each of these dates.
SELECT
NON EMPTY { [Measures].[Internet Sales Amount]} ON 0,
NON EMPTY { [Date].[Calendar].[Date] } ON 1
FROM [Adventure Works]
WHERE { [Date].[Date].&[20130105] : [Date].[Date].&[20130106] }
January 5, 2013 $32,681.44
January 6, 2013 $21,787.02
Result
Total value for these two dates is equal with the second querie's result - $54,468.46
I understand that in the first query it is user hierarchy and the second query it is attribute hierarchy from the Date dimension but I can not figure out which rule(s) tells to calculate these values differently.
If someone could explain this logic behind - it would be very helpful. Any link to some resource which explains this logic also could help.
BTW: I have created simple cube with simple Date dimension which consists just of attribute hierrarchies (date, month, year) and it still works like in the first query so it is not clear why it behaves like that.
I explored the reason for this behavior, and I think I have figured out the reason. The explanation below is based on the book SQL SERVER 2008 MDX Step by Step pages 51-58(especially Avoiding Reference Conflicts).
Your problem is a typical Reference Conflict problem.In MDX a hierarchy cannot be used more than once in a given tuple, but if you are using a USER Hierarchy and its under lying Attribute Hierarchy, you essentially by-pass this check. This is what happened in your query
In your first query you are using the User Hierarchy
[Date].[Calendar].[Month].&[2013]&1
In MDX a User Hierarchy is translated to Attribute Hierarchies. In your first query
SELECT
NON EMPTY { [Measures].[Internet Sales Amount] } ON 0,
NON EMPTY { [Date].[Calendar].[Month].&[2013]&1 } ON 1
FROM [Adventure Works] WHERE
{[Date].[Date].&[20130105]:[Date].[Date].&[20130106]}
you are using a User Hierarchy "[Date].[Calendar].[Month].&[2013]&1", which in its last level has "[Date].[Date]". Then in the where clause you use the same "[Date].[Date]" Attribute Hierarchy to filter. Since in the USER Hierarchy you have not used the leaf level, hence you have made a partial address, therefore the members and its ancestors are resolved. All the descendants are ignored in translation. Take a look at the below query(This is based on your first query,I have purposely removed your where clause).
with member [Measures].[CalendarYear] as [Date].[Calendar Year].currentmember.name
member [Measures].[CalendarSemester] as [Date].[Calendar Semester of Year].currentmember.name
member [Measures].[CalendarQuater] as [Date].[Calendar Quarter of Year].currentmember.name
member [Measures].[CalendarMonth] as [Date].[Month of Year].currentmember.name
member [Measures].[CalendarDate] as [Date].[Date].currentmember.name
SELECT
NON EMPTY { [Measures].[Internet Sales Amount] ,[Measures].[CalendarYear],[Measures].[CalendarSemester],[Measures].[CalendarQuater],[Measures].[CalendarMonth],[Measures].[CalendarDate]} ON 0,
NON EMPTY { [Date].[Calendar].[Month].&[2013]&[1] } ON 1
FROM [Adventure Works]
Result.
Notice that Calendar year, Semester and quarter all are showing non-default values. But we never used them. This shows that translation of User Hierarchy is done into underlying Attribute Hierarchies. Now take a look at Calendar, it is still showing "All Period". Since it was ignored.
Now if you add your where clause back, the Date still shows "All Period", there are two reasons
1) Because it was ignored in User Hierarchy translation ,
2)You used a range in where. If you replace your row axis tuple with your where tuple it will still show "All Period" as a range is based. However while resolving it will take just two dates.
Based on this while resolving your query, it had two translation for Date attribute hierarchy, one said to ignore it based on User Hierarchy, the other provided a range. This is where due to conflict the result is in-correct.
Now lets consider the query you gave me in your comment earlier
with member [Measures].[CalendarYear] as [Date].[Calendar Year].currentmember.name
member [Measures].[CalendarSemester] as [Date].[Calendar Semester of Year].currentmember.name
member [Measures].[CalendarQuater] as [Date].[Calendar Quarter of Year].currentmember.name
member [Measures].[CalendarMonth] as [Date].[Month of Year].currentmember.name
member [Measures].[CalendarDate] as [Date].[Date].currentmember.name
SELECT
NON EMPTY { [Measures].[Internet Sales Amount] ,[Measures].[CalendarYear],[Measures].[CalendarSemester],[Measures].[CalendarQuater],[Measures].[CalendarMonth],[Measures].[CalendarDate]} ON 0,
NON EMPTY { [Date].[Calendar].[Month].&[2013]&[1] } ON 1
FROM [Adventure Works]
WHERE {[Date].[Date].&[20130105]}
Result:
Notice that this time the resolution of a single member, was used instead of the User hierarchy resolution. Now this behavior might be due to the fact that one translation is giving "All Period" and the next is giving a member, hence the member won.
To further confirm this, I made a change to my AdventureWorks sample. The Date attribute hierarchy is based on "Simple Date" column. I exposed "Simple Date" as a separate attribute and processed my cube.
Take a look at the "Simple Date" query and results.
with member [Measures].[CalendarYear] as [Date].[Calendar Year].currentmember.name
member [Measures].[CalendarSemester] as [Date].[Calendar Semester of Year].currentmember.name
member [Measures].[CalendarQuater] as [Date].[Calendar Quarter of Year].currentmember.name
member [Measures].[CalendarMonth] as [Date].[Month of Year].currentmember.name
member [Measures].[CalendarDate] as [Date].[Date].currentmember.name
SELECT
NON EMPTY { [Measures].[Internet Sales Amount] ,[Measures].[CalendarYear],[Measures].[CalendarSemester],[Measures].[CalendarQuater],[Measures].[CalendarMonth],[Measures].[CalendarDate]} ON 0,
NON EMPTY { [Date].[Calendar].[Month].&[2013]&[1] } ON 1
FROM [Adventure Works]
WHERE
--{[Date].[Date].&[20130105]}
{[Date].[Simple Date].&[20130105]:[Date].[Simple Date].&[20130106]}
Results:

Blank dimension names while browsing SSAS cube

I recently started encountering strange problem as shown in image below. While browsing a SSAS cube, the Dimension Names appear blank.
Dimension: I have [Date].[Calendar Month].[Month]
Measure: [Services in 3 days]
After I run a query like
Select [Date].[Calendar Month].[Month] on 0 From [Service Cube]
then the Dimension Member Names show up in cube browser with different value for measure.
Any clues?
That's because you have blank members in [Date].[Calendar Month] hierarchy. To check 'em out, run the below MDX query:
WITH SET BlankMonth AS
FILTER([Date].[Calendar Month].CHILDREN, [Date].[Calendar Month].currentmember.MEMBERVALUE = '')
SELECT [Measures].[Services in 3 days] ON 0,
BlankMonth ON 1
FROM [Service Cube]

How to return the LastDate as a measure

This is the expression:
WITH
MEMBER [Date].[Calendar].[LastDate] AS
Tail(
nonempty(
[Date].[Calendar].MEMBERS,
[Measures].[Internet Sales Amount]
)
).Item(0)
MEMBER [Measures].[MeasureX] AS
[Date].[Calendar].[LastDate].member_value
SELECT
{
[Measures].[MeasureX]
} ON COLUMNS
FROM [Adventure Works];
The result is this:
How do I configure this so MeasureX returns the last date in the [Date].[Calendar] dimension?
The formula of a calculated member cannot return a member; you could use an icCube function for that ;-) but for SSAS perhaps creating a set of one member might do the trick for you. Then accessing the member could be done using the notation: mySet(0).
Hope that helps.

EXISTS not fully filtering as expected

If I run the following there’s a whole section of Customers that are (null) internet sales amount for both 2007 and 2008 – why is this? How do I use EXISTS to filter to just customers who have results for the years in the select
note: The choice of years could vary so InitialSet needs to be context aware hence I've used [Date].[Calendar Weeks].CURRENTMEMBER withing the EXISTS function.
WITH
SET [InitialSet] AS
EXISTS(
{[Customer].[Customer].[Customer].MEMBERS},
[Date].[Calendar Weeks].CURRENTMEMBER,
'Internet Sales'
)
SET [OrderedSet] AS
NONEMPTY
(
ORDER
(
[InitialSet],
[Measures].[Internet Sales Amount],
BDESC
)
,([Measures].[Internet Sales Amount],[Date].[Calendar Weeks].CURRENTMEMBER)
)
SELECT
{
[Date].[Calendar Weeks].[Calendar Year].&[2007],
[Date].[Calendar Weeks].[Calendar Year].&[2008]
} ON 0,
[OrderedSet] ON 1
FROM [Adventure Works]
WHERE (
[Measures].[Internet Sales Amount]
);
Sets are evaluated by Analysis Services by taking the WHERE clause into account, but not using any row or column settings. If you would like to evaluate the sets only for 2007 and 2008, you have to state that.
Actually, the [Date].[Calendar Weeks].CURRENTMEMBER in your first set will refer to the default member of the [Date].[Calendar Weeks] hierarchy, which is the All member.

How can I determine whether dimensions are related?

I am developing a query builder application that generates MDX and trying to get customer counts from a cube using the following, which works just fine:
WITH MEMBER MEASURES.X AS (
{ [Customer].[Gender].[Female]},
[Customer].[Customer].Children
).Count
SELECT Measures.X ON 0 FROM [Adventure Works]
However, if the user drags in a dimension that is not related to the customer like:
WITH MEMBER MEASURES.X AS (
{ [Customer].[Gender].[Female]},
{ [Employee].[Status].[Active], [Employee].[Status].[Inactive]},
[Customer].[Customer].Children
).Count
SELECT Measures.X ON 0 FROM [Adventure Works]
the count result obviously becomes incorrect.
Is there a way to determine whether a dimension is related to the customer so that I can exclude it from the generated MDX query?
This information can be retrieved from the cube through AMO. The Cube class contains all the cube metadata you'll need.
Solved the problem by using the Exists( Set_Expression1 , Set_Expression2 [, MeasureGroupName] ) function. No need to manually determine which dimensions are related. The Exists function filters out the unrelated tuples, leaving only the
{ [Customer].[Customer].Children, [Customer].[Gender].[Female]} set to do the count over.
Here is the MDX:
WITH MEMBER MEASURES.X AS Exists(
[Customer].[Customer].Children,
{[Customer].[Gender].[Female]}
*
{[Employee].[Status].[Active], [Employee].[Status].[Inactive]}
).Count
SELECT Measures.X ON 0 FROM [Adventure Works]