Top X of Top Y with RestOf 成员,其中 X 和 Y 是来自不同维度的层次结构

Top X of Top Y with RestOf member where X and Y are hierarchies from different dimensions

这很好用:

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];

编辑2

这是根据 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];

编辑3

以下顺序正确,因此成员 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];

编辑4

以下顺序正确,因此成员 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];

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

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

尝试在 ON ROWS 定义的开头添加 NON EMPTY。然后它只会 return 具有 Internet Order Count 度量值的组合(无论列上的度量)。这是限制交叉连接的正确方法。

如果您不想在 Internet 订单计数上使用 NON EMPTY,那么您需要在不同的度量上使用 NonEmpty(, [Measures].[A Different Measure])?

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

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]
    ) 

这似乎工作正常:

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];