如何通过同一层次结构中的多个项目过滤 Filter 函数中的度量

How to filter measure in the Filter function by multiple items from the same hierarchy

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

这是一个真实的例子:有一个多维数据集教育具有以下维度和度量

用户想要查看在 2010 学年和 2011 学年有一次或多次学生违规行为的学生的出勤率。

我需要使用 Filter 函数来完成此操作,因此我在下面编写了查询

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函数。有什么方法可以使查询正常工作吗?

您可以使用 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切片,同时你还需要Measure Filter.

  • 首先,为每个[学年]生成子select,仅selecting 年:

    ... 来自 (

    select {[学年].[学年].&[2010],[学年].[学年].&[2011]} 0 )

    来自[教育]

  • 其次,在顶层设置上使用HAVING或FILTER来获得你需要的东西

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

但是,很少有您的 MDX 浏览器足够智能,可以同时使用维度筛选器和度量组成员筛选器生成查询。即使像 SSMS/Excel 这样的重型产品也将此任务委托给纯 MDX 代码;

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

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:

的语法

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 年添加一个度量?添加它会显着降低复杂性。

最终查询可能如下所示:

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 部分。请参阅 here 如何将 StrToSet 函数与 SSRS 一起使用。你可以尝试类似的东西。