【问题标题】:How to filter measure in the Filter function by multiple items from the same hierarchy如何通过来自同一层次结构的多个项目在过滤器功能中过滤度量
【发布时间】:2015-02-16 20:03:11
【问题描述】:

我正在创建一个生成MDX 查询的应用程序。当用户使用Filter 函数时,我坚持实现一个场景,并且在逻辑表达式中,用户希望按同一层次结构中的多个成员对度量进行切片。

这是一个真实的例子:有一个立方体教育,具有以下维度和度量

  • 维度:学生、学年
  • 措施:学生出勤率、学生违规行为

用户希望查看在 2010 和 2011 学年有一次或多次学生违规的学生的学生出勤率。

我需要使用过滤器功能来完成这个,所以我在下面写了查询

SELECT [Measures].[Student Attendance] ON COLUMNS
FROM (
  SELECT 
    FILTER(
        [Student].[Student].[Student].Members, 
          (
            [Measures].[Student Infractions], 
            AGGREGATE(
                {
                  [School Year].[School Year].&[2010]
                 ,[School Year].[School Year].&[2011]
                }
            )
          ) > 1
    ) ON COLUMNS
  FROM [Education]
)

问题是当这个查询被执行时,它会抛出 'Query (4, 55) The Tuple function expects a tuple set expression for the 2 argument. A string or numeric expression was used.'

看起来无法在 Filter 函数中使用 Aggregate 函数。有什么方法可以让查询正常工作吗?

【问题讨论】:

    标签: mdx


    【解决方案1】:

    您有一个额外的方括号,如下所示,它是元组第二个参数的一部分 - 这可能是错误消息的原因:

    SELECT [Measures].[Student Attendance] ON COLUMNS
    FROM (
      SELECT 
        FILTER(
            [Student].[Student].[Student].Members, 
              (
                [Measures].[Student Infractions], 
                AGGREGATE(
                    {
                      [School Year].[School Year].&[2010]
                     ,[School Year].[School Year].&[2011]]   //<<<EXTRA BRACKET !
                    }
                )
              ) > 1
        ) ON COLUMNS
      FROM [Education]
    )
    

    所有逻辑都可以放在外部查询的WHERE 子句中,去掉sub-select

    SELECT [Measures].[Student Attendance] ON COLUMNS
    FROM   [Education]
    WHERE  (
            Filter
              (
                [Student].[Student].[Student].MEMBERS
               ,
                  AGGREGATE(
                     {[School Year].[School Year].&[2010] , [School Year].[School Year].&[2011]}
                     ,[Measures].[Student Infractions]    
              )
            > 1
           );
    

    编辑

    您的原始查询没有 AGGREGATE,但针对 AdvWrks 进行了测试,似乎执行正常:

    SELECT 
      [Measures].[Student Attendance] ON COLUMNS
    FROM 
    (
      SELECT 
          Filter
          (
            [Student].[Student].[Student].MEMBERS
           ,
              [Measures].[Student Infractions]
            * 
              ([School Year].[School Year].&[2010] + [School Year].[School Year].&[2011])
          )
        > 1 ON COLUMNS
      FROM [Education]
    );
    

    这是我编写的 AdvWrks 等效脚本 - 它运行正常:

    SELECT 
      [Measures].[Internet Sales Amount] ON 0
    FROM 
    (
      SELECT 
        Filter
        (
          [Product].[Product Categories].[Subcategory].MEMBERS
         ,
              [Measures].[Reseller Order Quantity]
            * 
              (
                [Date].[Calendar].[Calendar Year].&[2007]
              + 
                [Date].[Calendar].[Calendar Year].&[2008]
              )
          > 1
        ) ON 0
      FROM [Adventure Works]
    );
    

    编辑2

    好的-我应该更彻底地阅读MSDN!这是AGGREGATE 的语法:

    聚合(Set_Expression [ ,Numeric_Expression ])

    遵循此建议...

    SELECT 
      [Measures].[Student Attendance] ON COLUMNS
    FROM 
    (
      SELECT 
          Filter
          (
            [Student].[Student].[Student].MEMBERS
           ,
              AGGREGATE(
                {[School Year].[School Year].&[2010] , [School Year].[School Year].&[2011]}
                ,[Measures].[Student Infractions]    
          )
        > 1 ON COLUMNS
      FROM [Education]
    );
    

    【讨论】:

    • 为什么,额外的括号是一个错字。感谢您指出了这一点。我已经更正了我的问题中的查询。我不能使用切片器,因为选择应该在子选择中工作。子选择中不允许使用切片器。我不认为您评论中的最后两个查询可以满足我的需要,因为切片器还会在 2010、2011 学年之前过滤学生出勤率。无论如何,感谢您的快速回复!
    • @Alex 好的 - 我添加了对您原始脚本的修改。我使用了运算符+ 而不是函数AGGREGATE,现在看起来很开心。我不确定为什么一个有效而另一个无效的原因。
    • @Alex 我还删除了我之前的一项尝试 - 正如您指出的那样,WHERE 不允许在子选择中使用。我已经更正了帖子中的第二个脚本,以便它正确使用WHERE 子句来返回您的号码。我还找出了AGGREGATE 的正确语法,并在我的帖子末尾添加了脚本。
    • 为什么,感谢您的解决方案。根据您的示例,我的查询使用 Aggregate 函数。我现在唯一的问题是 Aggregate 函数不能用于计算的度量,因此我无法实现该场景的通用解决方案,但至少这对我来说是一个很好的起点。
    • whytheq,关于你的第一次编辑,它执行好了,但是我得到了错误的数字,在移动这部分 [Measures].[Student Infractions] * ([School Year].[School Year].& [2010] + [School Year].[School Year].&[2011]) ) 到 WITH MEMBER 区域我得到一个无限循环错误
    【解决方案2】:

    你可以使用HAVING子句

    With member hadInfraction 
    as (
       iif(sum( {[School Year].[School Year].&[2010],[School Year].[School Year].&[2011]},
                [Measures].[Student Infractions]) > 1, 1,0)
    )
       SELECT {[Measures].[Student Attendance] } ON 0,
         {[Student].[Student].[Student].Members}
    Having [Measures].[hadInfraction] =1
    On 1
    From Education 
    

    我几乎不使用 FILTER 功能 - 它速度慢且不灵活。 Having 允许您根据所需的任何计算成员过滤任何集合。

    编辑:只要您需要生成 MDX,那么您应该考虑使用所有 MDX 浏览器(Excel、SSMS 等)的通用方法:

    用户提供[School Year].[School Year].&[2010],[School Year].[School Year].&[2011]作为Cube slice,同时还需要Measure Filter。

    • 首先,为每个[学年]生成子选择,只选择 年:

      ... 来自(

      选择 {[School Year].[School Year].&[2010],[School Year].[School Year].&[2011]} on 0 )

      来自[教育]

    • 其次,在顶部使用 HAVING 或 FILTER 来获得所需的内容

    问题是你应该自己构造额外的计算成员,一般使用AGGREGATE(一般你需要默认的聚合函数)。因此,对于可视化编程查询,您可能能够在 100 种可能的场景中选择其中一种。

    但是,当您的 MDX 浏览器足够智能以使用维度过滤器和度量值组成员过滤器生成查询时,这种情况很少见。甚至像 SSMS/Excel 这样的重型产品也将这项任务委托给纯 MDX 代码;

    【讨论】:

    • 乔治,感谢您的回复。我需要一个针对我正在使用的工具的通用解决方案。我不能使用 Have,因为它不能用于子选择。此外,我不能使用 SUM 函数,因为可能有另一个具有不同聚合类型的度量而不是 Student Infractions; Filter 函数满足我的所有要求,除了通过来自同一层次结构的多个成员过滤度量,所以我希望有一种方法可以让 Filter 函数在我的场景中工作。
    • 您也可以在过滤器中使用该成员,但不能在子选择中使用,遗憾的是,您仅限于过滤器。使用聚合代替 SUM。另外,告诉我 subselect 的目的 - 与 WHERE hete 相比,您不会获得太多性能
    • 乔治,感谢您的澄清。子选择的目的是我正在实现一个工具,该工具允许用户通过添加越来越多的条件和过滤器来分解数据。每个分解级别代表一个 select 语句,其中包含父分解级别的子选择。
    【解决方案3】:

    那么,为什么不在多维数据集中添加 2010 年和 2011 年的度量?添加它会显着降低复杂性。

    最终查询可能如下所示:

    WITH [Measures].[Student Attendance For Selected Years] AS
    AGGREGATE(
                    {
                      STRTOSET('[School Year].[School Year].&[2010]
                     ,[School Year].[School Year].&[2011]') ---STRTOSET function allows for this part to be a parameter
                    },
                    [Measures].[Student Infractions]
             )
    
    SELECT [Measures].[Student Attendance] ON COLUMNS
     FROM [Education]
     WHERE FILTER([Student].[Student].children, [Measures].[Student Attendance For Selected Years]>1)
    

    您需要做的是构建参数并将其传递到 MDX 的 STRTOSET 部分。请参阅hereStrToSet 函数如何与 SSRS 一起使用。你可以试试类似的。

    【讨论】:

    • 我无法向多维数据集添加常规度量,因为我正在实现一个生成 MDX 查询的工具。如果 [Measures].[Student Infractions] 是计算量度,则您的示例将不起作用。这是聚合函数的限制
    • 然后去找一个计算好的成员。 WITH 子句创建计算成员,我在回答中使用了该成员。
    • 此外,StrToSet 允许您添加年份的动态值。据我猜测,2010 年和 2011 年是样本值,但作为最终产品,您需要动态地传递年份。
    • with 子句中定义的计算成员在子选择中不可用。所以我不能使用这种方法。
    • 听起来不是很粗鲁,但是当可能有其他解决方案时,为什么你会一心想使用子选择?我的解决方案不使用子选择。你必须有一个限制吗?
    猜你喜欢
    • 1970-01-01
    • 2013-06-11
    • 2020-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-19
    • 2021-11-18
    相关资源
    最近更新 更多