对共享维度上每个层次结构的一行进行快速 MDX 查询



处理包含由多个层次结构组成的UserGroups维度的 SSAS 多维数据集。 每个层次结构将用户分类为是否属于特定组。 用户可以属于多个组。

尝试为维度中的每个层次结构生成一个包含一行的表。 我想出的最佳方法如下:

WITH
    MEMBER [Measures].[Group Name] AS
        CASE
            WHEN [UserGroups].[Group A].CurrentMember.MemberValue <> 'All' THEN "Group A"
            WHEN [UserGroups].[Group B].CurrentMember.MemberValue <> 'All' THEN "Group B"
            -- More user groups...
            WHEN [UserGroups].[Group T].CurrentMember.MemberValue <> 'All' THEN "Group T"
            ELSE "Error"
        END
SELECT
{[Members].[Group Name], [Measures].[User Count], [Measures].[Revenue]} ON 0,
Order(
    UNION(
         [UserGroups].[Group A].&[True] *
        {[UserGroups].[Group B].[All]} *
        -- More user groups...
        {[UserGroups].[Group T].[All]},

         [UserGroups].[Group A].[All] *
        {[UserGroups].[Group B].&[True]} *
        -- More user groups...
        {[UserGroups].[Group T].[All]},
        -- A bunch more blocks so that there is one for each row.
         [UserGroups].[Group A].[All] *
        {[UserGroups].[Group B].[All]} *
        -- More user groups...
        {[UserGroups].[Group T].&[True]}
    ),
)
ON 1
FROM [Finances];

这将成功生成预期的表:

                    Group Name  User Count  Revenue
All  All  ... True  Group T     90          1800
...  ...  ... ...   ...         ...         ...
All  True ... All   Group B     20          400
True All  ... All   Group A     10          100

但是,查询非常慢。 任何给定的行都可以在大约 30 秒内单独计算。 当使用 UNION 语句合并行时,每增加一行似乎会导致计算时间呈指数级增长,而不是计算时间的预期线性增加。

  • 为什么观察到这种时间增加?
  • 有没有办法指示底层引擎单独计算每一行?
  • 有没有更好的方法来发出此查询?

我想你已经尝试过重新排列查询 - 如果你从 SELECT 中删除 UNION(...( 并在 WITH 子句中使其成为命名的 SET,这会有帮助吗?

WITH
    SET [RowSet] AS
       UNION(
         [UserGroups].[Group A].&[True] *
        {[UserGroups].[Group B].[All]} *
        -- More user groups...
        {[UserGroups].[Group T].[All]},

         [UserGroups].[Group A].[All] *
        {[UserGroups].[Group B].&[True]} *
        -- More user groups...
        {[UserGroups].[Group T].[All]},
        -- A bunch more blocks so that there is one for each row.
         [UserGroups].[Group A].[All] *
        {[UserGroups].[Group B].[All]} *
        -- More user groups...
        {[UserGroups].[Group T].&[True]}
    )
    MEMBER [Measures].[Group Name] AS
        CASE
            WHEN [UserGroups].[Group A].CurrentMember.MemberValue <> 'All' THEN "Group A"
            WHEN [UserGroups].[Group B].CurrentMember.MemberValue <> 'All' THEN "Group B"
            -- More user groups...
            WHEN [UserGroups].[Group T].CurrentMember.MemberValue <> 'All' THEN "Group T"
            ELSE "Error"
        END
SELECT
  {[Members].[Group Name], [Measures].[User Count], [Measures].[Revenue]} ON 0,
  Order(
    [RowSet],
)
ON 1
FROM [Finances];

ORDER 函数的目的是什么?我看不到你在订购什么?

再次只是在黑暗中射击,但我认为有时我注意到使用 UNION 和使用 + 运算符之间的效率差异 - 所以另一种选择:

WITH
    SET [RowSet] AS
       {
         [UserGroups].[Group A].&[True] *
        {[UserGroups].[Group B].[All]} *
        -- More user groups...
        {[UserGroups].[Group T].[All]}
       }
      +
       {
         [UserGroups].[Group A].[All] *
        {[UserGroups].[Group B].&[True]} *
        -- More user groups...
        {[UserGroups].[Group T].[All]}
       }
        -- A bunch more blocks so that there is one for each row.
      +
       {
         [UserGroups].[Group A].[All] *
        {[UserGroups].[Group B].[All]} *
        -- More user groups...
        {[UserGroups].[Group T].&[True]}
       }
    MEMBER [Measures].[Group Name] AS
      ...
      ...

抱歉,我没有确定 - 以上只是可能会幸运的选项!!最好与 Greg 尽可能详细地讨论,因为他将能够就立方体设计的可能修改为您提供可靠的建议。

最新更新