具有RestOf成员的Top Y的顶部X,其中X和Y是来自不同维度的层次结构

时间:2015-11-02 20:10:09

标签: ssas mdx

这很好用:

WITH 
  SET [AllCountries] AS [Country].[Country].MEMBERS 
  SET [AllStates]    AS [State-Province].[State-Province].MEMBERS 
  SET [Top2States] AS 
    Generate
    (
      [AllCountries]
     ,TopCount
      (
        (EXISTING 
          [AllStates])
       ,3
       ,[Measures].[Internet Order Count]
      )
    ) 
  MEMBER [State-Province].[All].[RestOfCountry] AS 
    Aggregate({(EXISTING {[AllStates]} - [Top2States])}) 
SELECT 
  {[Measures].[Internet Order Count]} ON COLUMNS
 ,{
      [AllCountries]
    * 
      {
        [State-Province].[All]
       ,[Top2States]
       ,[State-Province].[All].[RestOfCountry]
      }
  } ON ROWS
FROM [Adventure Works];

EXISTING关键字有很多帮助。

如果两个层次结构ON ROWS不是来自同一维度,就像上面的国家和州一样,那么我们会有以下内容:

WITH 
  SET [AllCountries] AS [Country].[Country].MEMBERS 
  SET [AllCats]      AS [Product].[Category].[Category].MEMBERS 
  SET [Top5Cats] AS 
    Generate
    (
      [AllCountries]
     ,TopCount
      (
        (EXISTING 
          [AllCats])
       ,5
       ,[Measures].[Internet Order Count]
      )
    ) 
  MEMBER [Product].[Category].[All].[RestOfProds] AS 
    Aggregate({(EXISTING {[AllCats]} - [Top5Cats])}) 
SELECT 
  {[Measures].[Internet Order Count]} ON COLUMNS
 ,{
      [AllCountries]
    * 
      {
        [Product].[Category].[All]
       ,[Top5Cats]
       ,[Product].[Category].[All].[RestOfCountry]

      }
  } ON ROWS
FROM [Adventure Works];

您可以在上面的结果中看到,针对每个国家/地区重复相同的类别集,顺序相同,即引擎未找到每个国家/地区的topCount。 EXISTING现在是多余的。

我们如何调整上面的第二个脚本,使其具有与顶级脚本类似的功能?

修改

更好的例子是以下使用Product。好像引擎正在为所有国家/地区找到TopCount,然后针对每个国家/地区设置相同的设置。我希望每个国家/地区TopCount

WITH 
  SET [AllCountries] AS 
    [Country].[Country].MEMBERS 
  SET [AllProds] AS 
    [Product].[Product].[Product].MEMBERS 
  SET [Top5Prods] AS 
    Generate
    (
      [AllCountries]
     ,TopCount
      (
        (EXISTING 
          [AllProds])
       ,5
       ,[Measures].[Internet Order Count]
      )
    ) 
  MEMBER [Product].[Product].[All].[RestOfProds] AS 
    Aggregate({(EXISTING {[AllProds]} - [Top5Prods])}) 
SELECT 
  {[Measures].[Internet Order Count]} ON COLUMNS
 ,NON EMPTY 
    {
        [AllCountries]
      * 
        {
          [Product].[Product].[All]
         ,[Top5Prods]
         ,[Product].[Product].[All].[RestOfProds]
        }
    } ON ROWS
FROM [Adventure Works];

EDIT2

这是Sourav创意的最新版本 - 遗憾的是RestOfProds成员无法正常运作:

WITH 
  SET [AllCountries] AS 
    [Country].[Country].MEMBERS 
  SET [AllProds] AS 
    [Product].[Product].[Product].MEMBERS 
  SET [Top5Prods] AS 
    Generate
    (
      [AllCountries] AS a
     ,
        {
            (
              a.Current
             ,[Product].[Product].[All]
            )
          + 
            //The top x prods
            TopCount
            (
              NonEmpty
              (
                a.Current * [AllProds]
               ,[Measures].[Internet Sales Amount]
              )
             ,5
             ,[Measures].[Internet Sales Amount]
            )
        }
    ) 
  SET [RestOfProds] AS 
    Extract
    (
      {[AllCountries] * [AllProds]} - [Top5Prods]
     ,[Product].[Product]
    ) 
  MEMBER [Product].[Product].[All].[RestOfProds] AS 
    Aggregate([RestOfProds]) 
SELECT 
  {[Measures].[Internet Sales Amount]} ON COLUMNS
 ,{
    [Top5Prods]
   ,
    [AllCountries] * [Product].[Product].[All].[RestOfProds]
  } ON ROWS
FROM [Adventure Works];

EDIT3

以下内容具有正确的顺序,以便成员RestOfProds始终遵循相应的前5名

WITH 
  SET [AllCountries] AS 
    [Country].[Country].MEMBERS 
  SET [AllProds] AS 
    [Product].[Product].[Product].MEMBERS 
  SET [Top5Prods] AS 
    Generate
    (
      [AllCountries] AS a
     ,{
        //The top x prods
        TopCount
        (
          NonEmpty
          (
            a.Current * [AllProds]
           ,[Measures].[Internet Sales Amount]
          )
         ,5
         ,[Measures].[Internet Sales Amount]
        )
      }
    ) 
  MEMBER [Product].[Product].[All].[RestOfProds] AS 
    Aggregate([Country].CurrentMember * [AllProds] - [Top5Prods]) 
SELECT 
  {[Measures].[Internet Sales Amount]} ON COLUMNS
 ,Generate
  (
    [AllCountries] AS X
   ,
      Order
      (
        Intersect
        (
          X.CurrentMember * [AllProds]
         ,[Top5Prods]
        )
       ,[Measures].[Internet Sales Amount]
       ,bdesc
      )
    + 
      {X.CurrentMember * {[Product].[Product].[All].[RestOfProds]}}
  ) ON ROWS
FROM [Adventure Works];

Edit4

以下内容具有正确的顺序,以便成员RestOfProds始终遵循相应的前5 +我在行上添加了另一组:

WITH 
  SET [2months] AS 
    {
      [Date].[Calendar].[Month].&[2007]&[9]
     ,[Date].[Calendar].[Month].&[2007]&[10]
    } 
  SET [AllCountries] AS 
    [Country].[Country].MEMBERS 
  SET [MthsCountries] AS 
    [2months] * [AllCountries] 
  SET [AllProds] AS 
    [Product].[Product].[Product].MEMBERS 
  SET [Top5Prods] AS 
    Generate
    (
      [MthsCountries] AS A
     ,{
        //The top x prods
        TopCount
        (
          NonEmpty
          (
            A.Current * [AllProds]
           ,[Measures].[Internet Sales Amount]
          )
         ,5
         ,[Measures].[Internet Sales Amount]
        )
      }
    ) 
  MEMBER [Product].[Product].[All].[RestOfProds] AS 
    Aggregate
    (
        ([Date].[Calendar].CurrentMember,[Country].CurrentMember) * [AllProds]
      - 
        [Top5Prods]
    ) 
SELECT 
  {[Measures].[Internet Sales Amount]} ON COLUMNS
 ,Generate
  (
    [MthsCountries] AS X
   ,
      Order
      (
        Intersect
        (
          X.Current * [AllProds]
         ,[Top5Prods]
        )
       ,[Measures].[Internet Sales Amount]
       ,bdesc
      )
    + 
      {X.Current * {[Product].[Product].[All].[RestOfProds]}}
  ) ON ROWS
FROM [Adventure Works];

3 个答案:

答案 0 :(得分:2)

在命名集上使用时,

EXISTING并没有什么区别,因为在布置轴成员之前创建了命名集。在你的情况下,GENERATE实际上只是创建静态集,然后在轴上一切都只是交叉连接。

要使TopCount脚本正常工作,您需要处理一组中的所有cross joins,以便一起评估所有内容。我不确定,但您可以尝试下面的内容:

WITH 
  SET [AllCountries] AS [Country].[Country].MEMBERS 
  SET [AllCats]    AS [Product].[Category].[Category].MEMBERS 
  SET [Top5Cats] AS 
    Generate
    (
      [AllCountries] as a
     ,
     {
     (a.current , [Product].[Category].[All] ) //The ALL member
     +   
     TopCount  //The top 2 categories
      (
        NonEmpty((a.current * [AllCats] ) , (a.CURRENT, [Measures].[Internet Order Count]))
       ,2
       ,[Measures].[Internet Order Count]      
      ) 
      }
    + 
    { //The rest of the members
    a.current * [AllCats] 
    - 
    a.current *{     
     TopCount
      (
        NonEmpty([AllCats] , (a.CURRENT, [Measures].[Internet Order Count]))
       ,2
       ,[Measures].[Internet Order Count]      
      ) 
      }
      }
    )

  MEMBER [Product].[Category].[All].[RestOfProds] AS 
    Aggregate({(EXISTING {[AllCats]} - [Top5Cats])}) 

SELECT 
  {[Measures].[Internet Order Count]} ON COLUMNS,
[Top5Cats] ON ROWS
FROM [Adventure Works];

修改 如果您需要RestOfCats成员,则可以添加此代码。

SET [RestOfCats] AS
EXTRACT
    (
     {
     [AllCountries] * [AllCats] 
     - 
     [Top5Cats]
     },
     [Product].[Category]
    )

MEMBER [Product].[Category].[All].[RestOfCats] AS
Aggregate([RestOfCats])

编辑2

继续您的示例,在定义中另外删除“All”成员。

  SET [RestOfProds] AS 
    Extract
    (
      {[AllCountries] * [AllProds]} - [Top5Prods] - [AllCountries]*[Product].[Product].[All]
     ,[Product].[Product]
    ) 

答案 1 :(得分:1)

如果要在同一维度中交叉连接多个层次结构,则仅显示有效组合。这称为自动存在,它解释了为什么第一个查询的工作方式与您想要的一样。

当交叉连接来自不同维度的层次结构时,不会发生自动存在。我认为这解释了第二个查询中返回的奇数组合。

尝试在ON ROWS定义的开头添加NON EMPTY。然后它将只返回具有互联网订单计数度量值的组合(列上的任何度量)。这是限制交叉连接的正确方法。

如果您不想在互联网订单计数上使用非空,那么您需要在不同的度量上使用NonEmpty(,[Measures]。[A Different Measure])?

编辑:看起来该问题与自动存在无关,但与每个国家/地区执行不同的TopCount有关。所以这个信息可以帮助别人,但不是这个问题的答案。

答案 2 :(得分:1)

这似乎工作正常:

WITH 
  SET [AllCountries] AS 
    [Country].[Country].MEMBERS 
  SET [AllProds] AS 
    [Product].[Product].[Product].MEMBERS 
  SET [Top5Prods] AS 
    Generate
    (
      [AllCountries] AS a
     ,{
          (
            a.CurrentMember
           ,[Product].[Product].[All]
          )
        + 
            //The top x prods
            a.CurrentMember
          * 
            TopCount
            (
              [AllProds]
             ,5
             ,[Measures].[Internet Sales Amount]
            )
      }
    ) 
  MEMBER [Product].[Product].[All].[Other Products] AS 
    Aggregate
    (
        [Country].CurrentMember * [Product].[Product].[Product].MEMBERS
      - 
        [Top5Prods]
    ) 
SELECT 
  {[Measures].[Internet Sales Amount]} ON COLUMNS
 ,Hierarchize(
    {
     [Top5Prods]
    ,[AllCountries] * [Product].[Product].[All].[Other Products]
    }
) ON ROWS
FROM [Adventure Works];