Except
works quite quickly for this scenario. Find all customers who had sales in 2008 then exclude any of those customers who had sales in 2006/2007. This leaves the customers who have sales in 2008 but not 2006/2007.
I played with using the Filter
function but it was very slow.
There will be a solution using IIF
with null
values as one of the return values that will be quick but I can't figure it out.
WITH
MEMBER MEASURES.[Returning Customers] AS
Count
(
Except
(
NonEmpty
(
[Customer].[Customer].[Customer].MEMBERS
,
{[Measures].[Internet Sales Amount]}*
{[Date].[Calendar Year].&[2008]}*
[Customer].[Customer Geography].CurrentMember
)
,NonEmpty
(
[Customer].[Customer].[Customer].MEMBERS
,
{[Measures].[Internet Sales Amount]}*
{
[Date].[Calendar Year].&[2006]
,[Date].[Calendar Year].&[2007]
}*
[Customer].[Customer Geography].CurrentMember
)
)
)
SELECT
[Date].[Calendar].[Calendar Year].MEMBERS
*
MEASURES.[Returning Customers] ON 0
,{[Customer].[Customer Geography].[Country].MEMBERS} ON 1
FROM [Adventure Works]
WHERE
[Date].[Calendar Year].&[2008];
Your scenario was very specific - so there is no point displaying any year other than 2008.
Here is a great reference as a place to start investigating to returning customer scripts:
http://cwebbbi.wordpress.com/2010/10/08/counting-new-and-returning-customers-in-mdx/
I think, in terms of performance, named sets should be used sparingly but when using set based functions they can actually increase performance so maybe, because we are using Except
named sets might speed things up:
WITH
SET [2008customers] AS
NonEmpty
(
[Customer].[Customer].[Customer].MEMBERS
,
{[Measures].[Internet Sales Amount]} * {[Date].[Calendar Year].&[2008]}
)
SET [20062007customers] AS
NonEmpty
(
[Customer].[Customer].[Customer].MEMBERS
,
{[Measures].[Internet Sales Amount]}
*
{
[Date].[Calendar Year].&[2006]
,[Date].[Calendar Year].&[2007]
}
)
MEMBER MEASURES.[Returning Customers] AS
Count
(
Except
(
[2008customers] * [Customer].[Customer Geography].CurrentMember
,
[20062007customers] * [Customer].[Customer Geography].CurrentMember
)
)
SELECT
[Date].[Calendar].[Calendar Year].MEMBERS
*
{
MEASURES.[Returning Customers]
,[Measures].[Customer Count]
} ON 0
,{[Customer].[Customer Geography].[Country].MEMBERS} ON 1
FROM [Adventure Works]
WHERE
[Date].[Calendar Year].&[2008];
This is a more general version of your original problem. Rather than naming the years it looks at customers from the current year in the table who are not found in the previous 2 years:
WITH
MEMBER MEASURES.[Returning Customers] AS
Count
(
Except
(
NonEmpty
(
[Customer].[Customer].[Customer].MEMBERS
,
{[Measures].[Internet Sales Amount]}*
{[Date].[Calendar Year].CurrentMember}*
[Customer].[Customer Geography].CurrentMember
)
,NonEmpty
(
[Customer].[Customer].[Customer].MEMBERS
,
{[Measures].[Internet Sales Amount]}*
(
[Date].[Calendar Year].CurrentMember.Lag(1)
:
[Date].[Calendar Year].CurrentMember.Lag(2)
)*
[Customer].[Customer Geography].CurrentMember
)
)
)
SELECT
[Date].[Calendar].[Calendar Year].MEMBERS
*
{
[Measures].[Customer Count]
,MEASURES.[Returning Customers]
} ON 0
,{[Customer].[Customer Geography].[Country].MEMBERS} ON 1
FROM [Adventure Works]
WHERE
NULL : [Date].[Calendar Year].&[2008];
Trying to figure out what happened in 2006?!
OLAP
based thenMDX
is the correct choice – whytheqMDX
script you are struggling with – whytheqOLAP
cubes if the administrator is just going to query the underlying database? – whytheq