Limiting date range using Filter - ssas

Without using the colon operator how do I filter the set AllDates to just 05Jan2005 to 10Jan2006?
WITH
SET [AllDates] AS
[Date].[Date].[Date].MEMBERS
MEMBER [Measures].[DTkey] AS
[Date].[Date].CurrentMember.Member_Key
MEMBER [Measures].[DTmemValue] AS
[Date].[Date].CurrentMember.MemberValue
MEMBER [Measures].[DTvalue] AS
[Date].[Date].CurrentMember.Value
SELECT
{[Measures].[DTmemValue]} ON 0
,Filter
(
[AllDates]
,
[Measures].[DTmemValue] > 0
) ON 1
FROM [Adventure Works];

I don't have Adv Wks but tested the below on mine and it worked well.
Is this what you're looking for?
WITH
SET [AllDates] AS
[Date].[date].[date].members
MEMBER [Measures].[DTkey] AS
[Date].[date].CurrentMember.Member_Key
MEMBER [Measures].[DTmemValue] AS
[Date].[date].CurrentMember.MemberValue
MEMBER [Measures].[DTvalue] AS
[Date].[date].CurrentMember.Value
SELECT
{[Measures].[DTmemValue]} ON 0
,Filter
(
[AllDates]
,
CDate([Measures].[DTmemValue]) >= CDate("01/05/2005")
and CDate([Measures].[DTmemValue]) <= CDate("01/10/2006")
) ON 1
FROM [Adventure Works];

WITH
SET [AllDates] AS
[Date].[Date].[Date].MEMBERS
MEMBER [Measures].[DTkey] AS
[Date].[Date].CurrentMember.Member_Key
MEMBER [Measures].[DTmemValue] AS
[Date].[Date].CurrentMember.MemberValue
MEMBER [Measures].[DTvalue] AS
[Date].[Date].CurrentMember.Value
SELECT
{[Measures].[DTmemValue]} ON 0
,Filter
(
[AllDates]
,
CDate([Measures].[DTmemValue]) > CDate("2006-01-01")
) ON 1
FROM [Adventure Works];
More details about MDX Filtering can be found: http://chrish.com.au/blog/filtering-in-mdx/

Related

MDX query with nested aggregations

WITH
MEMBER [Measures].[newCalculatedMeasure] AS
Sum
(
Filter
(
Descendants
(
[Date].[28 Days Month Calendar].CurrentMember
,2
,LEAVES
)
,
[Measures].[mymeasure] * 10
>
Avg
(
Filter
(
Descendants
(
[Date].[28 Days Month Calendar].CurrentMember
,2
,LEAVES
)
,
[Measures].[mymeasure] > 0
)
,[Measures].[mymeasure]
)
)
,[Measures].[mymeasure]
)
SELECT
[Date].[28 Days Month Calendar].MEMBERS ON 0
,[Measures].[newCalculatedMeasure] ON 1
FROM [cube];
Above query is not evaluating the inside average function, whereas if i replace that with the actual average, its working fine
Can somebody tell me whats wrong with the above measure..
Does splitting the measure into named sets help with this context issue?
WITH
SET [MYSET] AS
Descendants
(
[Date].[28 Days Month Calendar].CurrentMember
,2
,LEAVES
)
SET [MYSETFILTERED] AS
Filter
(
[MYSET]
,
[Measures].[mymeasure] > 0
)
MEMBER [Measures].[newCalculatedMeasure] AS
Sum
(
Filter
(
[MYSET]
,
[Measures].[mymeasure] * 10 > Avg([MYSETFILTERED],[Measures].[mymeasure])
)
,[Measures].[mymeasure]
)
SELECT
[Date].[28 Days Month Calendar].MEMBERS ON 0
,[Measures].[newCalculatedMeasure] ON 1
FROM [cube];
Named sets with aggregates can sometimes impact performance so please excuse me if the above slows everything up.

Create Set to get Last month of Each Year

I would like to create a set that returned the last Date for each year. For example all previous years would return December, but the current year would only return the current month.
WITH
SET testset AS
NonEmpty
(
Generate
(
{
OpeningPeriod([Date].[Calendar].[Month])
:
ClosingPeriod([Date].[Calendar].Month)
}
,{[Date].[calendar].CurrentMember}
)
,[Measures].[Sale Amount]
)
SELECT
NON EMPTY
(
[Measures].[Sale Amount]
,[Date].[Year].[Year]
) ON 0
,NON EMPTY
[testset] ON 1
FROM [Cube]
Here is an example of a script that returns the values for each month. I've tried using tail and lastchild, but that only returns the most recent. I would like it to return for every Year.
In terms of just the last month - ignoring whether there is data for it or not the following:
WITH
SET [AllYears] AS
[Date].[Calendar].[Calendar Year].MEMBERS
SET [LastMths] AS
Generate
(
[AllYears] AS S
,Tail
(
Descendants
(
S.CurrentMember
,[Date].[Calendar].[Month]
)
,1
)
)
SELECT
{} ON 0
,[LastMths] ON 1
FROM [Adventure Works];
Returns this:
If I want to adapt the above so that it is the last month per year that has data for a specific measure then wrap NonEmpty around the set created by Descendants:
WITH
SET [AllYears] AS
[Date].[Calendar].[Calendar Year].MEMBERS
SET [LastMths] AS
Generate
(
[AllYears] AS S
,Tail
(
NonEmpty //<<new
(
Descendants
(
S.CurrentMember
,[Date].[Calendar].[Month]
)
,[Measures].[Internet Sales Amount] //<<new
)
,1
)
)
SELECT
{} ON 0
,[LastMths] ON 1
FROM [Adventure Works];
It now gives us this:
We can then add in the tuple you have on rows (I have used the attribute hierarchy this time for years as [Date].[Calendar] is already in use)
WITH
SET [AllYears] AS
[Date].[Calendar].[Calendar Year].MEMBERS
SET [LastMths] AS
Generate
(
[AllYears] AS S
,Tail
(
NonEmpty
(
Descendants
(
S.CurrentMember
,[Date].[Calendar].[Month]
)
,[Measures].[Internet Sales Amount]
)
,1
)
)
SELECT
NON EMPTY
(
[Measures].[Internet Sales Amount]
,[Date].[Calendar Year].[Calendar Year]
) ON 0
,[LastMths] ON 1
FROM [Adventure Works];
Now we get this:
#Whytheq has already given a very good solution. Treat this as an alternative. This might be a tad faster as it doesn't use the GENERATE function (not sure though!).
Have a calculated/cube measure which basically tells whether a month is the last month of the year. Then select those months out of the set of months.
with member measures.islastchild as
iif
(
[Date].[Calendar].currentmember is
[Date].[Calendar].currentmember.parent.parent.parent.lastchild.lastchild.lastchild,
1,
null
)
The member measures.islastchild returns 1 if the month is the last month of the year. Else it would return null.
set lastmonths as
filter(
[Date].[Calendar].[Month].members,
measures.islastchild = 1
)
The set lastmonths is then the set you need.
edit
To further improve the performance, you can NonEmpty function instead of the iterative FILTER function.
set lastmonths as
NonEmpty(
[Date].[Calendar].[Month].members,
measures.islastchild
)
select lastmonths on 1,
{} on 0
from [Adventure Works]
EDIT 2: To get the last non month with sales
with member measures.islastnonemptychild as
iif
(
[Date].[Calendar].currentmember is
TAIL(NonEmpty([Date].[Calendar].currentmember.parent.parent.parent.lastchild.lastchild.children, [Measures].[Sale Amount])).ITEM(0),
1,
null
)
set nonemptylastmonths as
NonEmpty(
[Date].[Calendar].[Month].members,
measures.islastnonemptychild
)

Moving Average of Last 24 months

I have this calculated member which calculates a moving average for the last 12 months:
iif(IsEmpty(Sum({[Time].[Month].CurrentMember:NULL},
[Measures].[Count])), NULL,
Avg
(
[Time].[Month].CurrentMember.Lag(11) :
[Time].[Month].CurrentMember,
[Measures].[Count]
))
The iif condition is in place because I don't want to get values for future months (with no value), which I do get without it.
What I want to do is have this measure only for the last 24 months since the last not empty month.
I've tried with Tail and Lag but with no luck (I would post my attempts here but after many tries I deleted them and would really not know where to begin again).
Thanks to #whytheq this is the final solution that I used:
CREATE DYNAMIC SET CURRENTCUBE.[FirstEmptyMonth]
AS { Tail
(
NonEmpty
(
[Time].[Month].MEMBERS
,[Measures].[Count]
)
,1
).Item(0).NextMember };
CREATE DYNAMIC SET CURRENTCUBE.[MonthsToIgnore]
AS {[FirstEmptyMonth].Item(0) : NULL}
+
{NULL : [FirstEmptyMonth].Item(0).Lag(25)} ;
CREATE MEMBER CURRENTCUBE.[Measures].[Moving Average]
AS IIF
(
Intersect({[Time].[Month].CurrentMember},[MonthsToIgnore]).Count = 1
,null
,Avg
(
[Time].[Month].CurrentMember.Lag(11) : [Time].[Month].CurrentMember
,[Measures].[Count]
)
);
In AdvWrks I've got this:
WITH
SET [FutureMonthsWithNoData] AS
{
Tail
(
NonEmpty
(
[Date].[Calendar].[Month].MEMBERS
,[Measures].[Internet Sales Amount]
)
,1
).Item(0).NextMember
: NULL
}
MEMBER [Measures].[blah] AS
IIF
(
Intersect
(
{[Date].[Calendar].CurrentMember}
,[FutureMonthsWithNoData]
).Count
= 1
,null
,1
)
SELECT
{
[Measures].[Internet Sales Amount]
,[Measures].[blah]
} ON 0
,[Date].[Calendar].[Month].MEMBERS ON 1
FROM [Adventure Works];
It returns this:
So what I am saying is that you could create this initial set of FutureDatesWithNoData and then use that set to create a condition within your script. The set would be (I think) this in your cube:
SET [FutureMonthsWithNoData] AS
{
Tail
(
NonEmpty
(
[Time].[Month].[Month].MEMBERS
,[Measures].[Count]
)
,1
).Item(0).NextMember
: NULL
}
Your measure would then be as follows:
IIF
(
Intersect
(
{[Time].[Month].CurrentMember}
,[FutureMonthsWithNoData]
).Count
= 1
,NULL
,Avg
(
[Time].[Month].CurrentMember.Lag(11) : [Time].[Month].CurrentMember
,[Measures].[Count]
)
)
If you want to also exclude months prior to 24 months ago then this script sums up the logic:
WITH
SET [FistEmptyMonth] AS
{
Tail
(
NonEmpty
(
[Date].[Calendar].[Month].MEMBERS
,[Measures].[Internet Sales Amount]
)
,1
).Item(0).NextMember
}
SET [MonthsToIgnore] AS
{[FistEmptyMonth].Item(0) : NULL}
+
{NULL : [FistEmptyMonth].Item(0).Lag(24)}
MEMBER [Measures].[blah] AS
IIF
(
Intersect({[Date].[Calendar].CurrentMember},[MonthsToIgnore]).Count = 1
,null
,1
)
SELECT
{[Measures].[Internet Sales Amount]} ON 0
,[Date].[Calendar].[Month].MEMBERS ON 1
FROM [Adventure Works];

Checking Multiple condition in case statement using MDX query

How to write the below case statement in mdx.I moved the below mentioned columns in the fact table.
sum(case when IsSummary = 1 and IsAudited = 1 and FinalAuditFlag = 1 then 1
else 0 end) AuditsCompleted,--Count - Completed Audits
i tried the below MDX query.
WITH
MEMBER [Measures].[count]
AS
(
case ([Measures].currentmember )
when 0 then ([Measures].[Is Summary] )
else 1
end
)
Select
{[Measures].[count]} on 0,
[Dim_table1].[TableId].members on 1
from [Dsv]
What you have done is almost correct. Just change .currentmember to an actual measure in your cube. Currently when you have the following it is referring to itself i.e. currentmember by the black arrow it referring to the measure count by the black arrow...
This is in AdvWrks:
SELECT
{[Measures].[Internet Sales Amount]} ON 0
,{[Product].[Product Categories].[Category]} ON 1
FROM [Adventure Works];
It returns this:
If I want to replace the empty cell for Components the we can use CASE:
WITH
MEMBER [Measures].[count] AS
CASE [Measures].[Internet Sales Amount]
WHEN 0 THEN "XXX"
ELSE [Measures].[Internet Sales Amount]
END ,format_string = "#,###,##0"
SELECT
{
[Measures].[count]
} ON 0
,{[Product].[Product Categories].[Category]} ON 1
FROM [Adventure Works];
This now returns this:
IIF is used a lot more in MDX than CASE - IIF is nearly always faster. So the above equivalent using IIF is the following:
WITH
MEMBER [Measures].[count] AS
IIF
(
[Measures].[Internet Sales Amount] = 0
,"XXX"
,[Measures].[Internet Sales Amount]
)
,format_string = "#,###,##0"
SELECT
{[Measures].[count]} ON 0
,{[Product].[Product Categories].[Category]} ON 1
FROM [Adventure Works];
I am assuming that your requirement is to find the sum over all the members of [Dim Table1].[TableID] hierarchy.
If so, then the below should work for you:-
WITH MEMBER Measures.[Count] AS
SUM(
[Dim_table1].[TableId].CHILDREN,
[Measures].[Is Summary] * [Measures].[Is Audited] * [Measures].[Final Audited Flag] //If any is 0, it's 0, else 1
)
SELECT Measures.[Count]
FROM [Dsv]
Let me know if further slicers are needed to be added or if my understanding is incorrect.

MDX Start and End Time per transaction

I hope you can help i have tried so many way to try get this right with no luck. I am trying to get out the player account number the date and start and end date time and maybe calculate the play duration between the start and end times.
I would like the output to look something like this.
PlayerAccount | GamingDate | StartTime | EndTime | PlayDuration | ActualWin
I always seem to return the start and end time for the whole day and not Per account.
WITH
SET [MySet] AS
[Customer].[Player Account Number].Children*
Head
(
NonEmpty
(
[Start Time].[Hour].Children
,[Measures].[Actual Win]
)
,1
)*
Tail
(
NonEmpty
(
[End Time].[Hour].Children
,[Measures].[Actual Win]
)
,1
)
SELECT
{[Measures].[Actual Win]} ON 0
,{[MySet]} ON 1
FROM
(
SELECT
[Customer].[Player Account Number].&[1040002184]
:
[Customer].[Player Account Number].&[1040002198] ON 0
FROM Ratings
)
WHERE
{[Gaming Date].[Full Date].&[20150101]};
Usually first date and last date would be measures. If you only want results for those two player then use the WHERE clause rather than a sub-select:
WITH
MEMBER [Measures].[fDate] AS
Head
(
NonEmpty
(
[Start Time].[Hour].MEMBERS
,[Measures].[Actual Win]
)
).Item(0).Item(0).Member_Caption
MEMBER [Measures].[lDate] AS
Tail
(
NonEmpty
(
[End Time].[Hour].MEMBERS
,[Measures].[Actual Win]
)
).Item(0).Item(0).Member_Caption
SELECT
{
[Measures].[fDate]
,[Measures].[lDate]
,[Measures].[Actual Win]
} ON 0
,{[Customer].[Player Account Number].Children} ON 1
FROM Ratings
WHERE
([Gaming Date].[Full Date].&[20150101],
{ [Customer].[Player Account Number].&[1040002184]
,[Customer].[Player Account Number].&[1040002198]});
This is a working AdvWrks script which does the sort of thing you're trying to achieve:
WITH
MEMBER [Measures].[firstDate] AS
Head
(
NonEmpty
(
[Date].[Date].[Date].MEMBERS
,[Measures].[Internet Sales Amount]
)
).Item(0).Item(0).Member_Caption
MEMBER [Measures].[lastDate] AS
Tail
(
NonEmpty
(
[Date].[Date].[Date].MEMBERS
,[Measures].[Internet Sales Amount]
)
).Item(0).Item(0).Member_Caption
SELECT
{
[Measures].[Internet Sales Amount]
,[Measures].[firstDate]
,[Measures].[lastDate]
} ON 0
,NON EMPTY {[Promotion].[Promotion].MEMBERS} ON 1
FROM [Adventure Works];
If you'd rather pull back a member instead of using Measures I think the GENERATE function will work like this AdvWrks example:
WITH
SET [aSet] AS
Generate
(
[Promotion].[Promotion].MEMBERS
,
[Promotion].[Promotion].CurrentMember
*
Head
(
NonEmpty
(
[Date].[Date].[Date].MEMBERS
,[Measures].[Internet Sales Amount]
)
)
)
SELECT
{[Measures].[Internet Sales Amount]} ON 0
,NON EMPTY
{[aSet]} ON 1
FROM [Adventure Works];
Thanks a million whytheq it seems like that .Item(0).Item(0).Member_Caption made all the difference the results seem to be come out right now. The final solution looks like this now..
with set [MySet]
as
[Casino Hierarchy].[Casino Key].children *
[Gaming Date].[Date].currentmember *
[Customer].[Player Account Number].children *
[Start Time].[Hour].children
member [measures].[Mindate]
as
HEAD(nonempty([End Time].[Hour].children,[Measures].[Actual Win]),1).Item(0).Item(0).Member_Caption
member [measures].[Maxdate]
as
TAIL(nonempty([Start Time].[Hour].children,[Measures].[Actual Win]),1).Item(0).Item(0).Member_Caption
select non empty
{
[Measures].[Actual Win],[measures].[Mindate],[measures].[Maxdate]
} on 0, non empty
{
[Customer].[Player Account Number].children
} on 1
from
(
select ([Customer].[Player Account Number].&[1040002184]:[Customer].[Player Account Number].&[1040002198]) on 0 from Ratings
)
where
{
[Gaming Date].[Full Date].&[20150101]
}
You are having a static set(which always return the same members). Use the EXISTING keyword to evaluate the Start and end time in the current context.
with member [Measures].[StartDate] as
EXISTING
HEAD(
nonempty(
[Start Time].[Hour].Children,[Measures].[Actual Win]
) ,1
).ITEM(0).ITEM(0).MEMBERVALUE
member [Measures].[EndDate] as
EXISTING
TAIL(
nonempty(
[End Time].[Hour].children,[Measures].[Actual Win]
) ,1
).ITEM(0).ITEM(0).MEMBERVALUE
select
{
[Measures].[Actual Win],
[Measures].[StartDate],
[Measures].[EndDate]
} on 0,
[Customer].[Player Account Number].children on 1
from
(
select (
[Customer].[Player Account Number].&[1040002184]:
[Customer].[Player Account Number].&[1040002198]
) on 0
from Ratings
)
where {[Gaming Date].[Full Date].&[20150101]}
Have rearranged the [Customer].[Player Account Number] so that dates are evaluated in the context of each player account. Hope that's fine!
Edit.
A simplified AdWrks version of this approach is as follows: still not quite working:
WITH
SET [aSet] AS
(EXISTING
Head
(
NonEmpty
(
[Date].[Date].[Date].MEMBERS
,[Measures].[Internet Sales Amount]
)
))
SELECT
{[Measures].[Internet Sales Amount]} ON 0
,NON EMPTY
{[Promotion].[Promotion].MEMBERS * [aSet]} ON 1
FROM [Adventure Works];