5

在 Chris Web 的帖子之后,我正在寻找一种快速的方法来找到客户的最后一次购买。

我使用如下 MDX 语句:

WITH FUNCTION previous_buys() AS tail( nonempty({NULL:[Time].[Time].currentmember.prevmember} ,[measures].[sales amt]),1)
MEMBER [last buy] as previous_buys().(0).key

select [measures].[last buy] on 0
,      [Customers].[Customers].[name].members on 1
from [Store Sales]
where [Time].[Time].[day].&[2015-12-20T00:00:00.000]

这符合预期,但需要很长时间。有没有一种简单的方法可以以某种方式加速这个查询。由于 icCube 与 Microsoft MDX 有些不同,我不能只是复制 Chris Web 的解决方案。

有任何想法吗?

4

2 回答 2

2

这个解决方案的主要问题是我们评估 {NULL:[Time].[Time].currentmember.prevmember} 计数成员时的可伸缩性。

我认为使用带有 Head 函数的 Reverse 不会评估整个集合,但 Empty 函数的当前实现会“物化”集合。这意味着我们正在评估所有成员。还不是一个有效的解决方案。

另一个更优雅的解决方案是使用递归函数。这将大大减少被评估的成员数量。

WITH 
  FUNCTION previous_buys(t_) AS IIF( (t_,[Measures].[Amount]) = NULL,  previous_buys(t_.prevMember), t_ )
  MEMBER [last buy] as previous_buys( [Time].[Calendar].current).name

SELECT 
  [measures].[last buy] on 0,
  [Customers].[Geography].[Region]  on 1
FROM [Sales]
WHERE [Time].[Calendar].[Year].[2006].[Q1 2006].[Jan 2006].[8 Jan 2006]

如果您有很多空日期,则可能会使算法复杂一些,降低到一个月的水平以检查空日期。这将在一次迭代中评估整个月,而不是我们在日版本中的 30/31。


最后一个也是最快的一个数量级是依靠icCube的聚合引擎。我们在这里想要的是一个返回最后一个存在日期的度量。

这个想法是添加一个以日期作为输入值,以最大值作为聚合方法的度量。然后我们将使用 eval - 重要的是因为我们正在缓存子立方体 - 在带有这个新度量的集合上。

于 2016-01-24T11:01:48.467 回答
0

使用SSASagainst相对较快AdvWrks。我合并了两个自定义结构(需要更改,FUNCTION因为我认为这不是 MS 实现的一部分mdx):

WITH 
  MEMBER [Measures].[previous_buys] AS 
    Tail
    (
      NonEmpty
      (
        {NULL : [Date].[Calendar].CurrentMember.PrevMember}
       ,[Measures].[Internet Sales Amount]
      )
    ).Item(0).Item(0).Member_Key 
SELECT 
  NON EMPTY 
    [Measures].[previous_buys] ON 0
 ,NON EMPTY 
    [Product].[Product Categories].[Product] ON 1
FROM [Adventure Works]
WHERE 
  [Date].[Calendar].[Date].&[20071015];

结果如下:

在此处输入图像描述

于 2016-01-21T10:55:54.463 回答