mdx 非空排除存在的值

mdx nonempty exclude value that exists

我对 Nonempty() 函数的理解是,它采用第一个集合表达式,将其应用于第二个集合表达式,并删除第二个表达式中没有值的表达式。

我有

WITH
SET [Date Range] AS
    Filter(
        [Date].[Date].[Date],
        [Date].[Date].CurrentMember.Member_Value >= CDate(@StartDateParam) AND
        [Date].[Date].CurrentMember.Member_Value <= CDate(@EndDateParam)
    )

MEMBER [Measures].[DateValue] AS
    [Date].[Date].CurrentMember.Member_Value

SELECT
{
    [Measures].[DateValue],
    [Measures].[Work Item Count]
} ON COLUMNS,
{
    CrossJoin(
        [Date Range],
        --NonEmpty(
            [Work Item].[System_State].[System_State]
        --  ,[Measures].[Work Item Count]
        --)
    )
} ON ROWS
FROM [Team System]

哪个returns

Date     | State    | DateValue  | WorkItemCount
2/1/2015 | Active   | 2/1/2015.. | 2
2/1/2015 | Resolved | 2/1/2015.. | (null)
2/2/2015 | Active   | 2/2/2015.. | 1
2/2/2015 | Resolved | 2/2/2015.. | 1
2/3/2015 | Active   | 2/3/2015.. | 0
2/3/2015 | Resolved | 2/3/2015.. | 2

当我取消注释上面的非空代码时, 我得到:

Date     | State    | DateValue  | WorkItemCount
2/1/2015 | Resolved | 2/1/2015.. | (null)
2/2/2015 | Resolved | 2/2/2015.. | 1
2/3/2015 | Resolved | 2/3/2015.. | 2

我期待得到:

Date     | State    | DateValue  | WorkItemCount
2/1/2015 | Active   | 2/1/2015.. | 2
2/2/2015 | Active   | 2/2/2015.. | 1
2/2/2015 | Resolved | 2/2/2015.. | 1
2/3/2015 | Resolved | 2/3/2015.. | 2

这里发生了什么?

这发生在 SQL Server 2014 上,因此 SSAS MDX NonEmpty issue 中的答案不适用

NonEmpty() 仅删除那些给出 null*null 的交叉连接结果。当你遇到 Resolved*null 这样的情况时,NonEmpty 不起作用。此外,该方法不会为您提供最佳性能。试试这个:

WITH
SET [Date Range] AS
Filter(
    [Date].[Date].[Date],
    [Date].[Date].CurrentMember.Member_Value >= CDate(@StartDateParam) AND
    [Date].[Date].CurrentMember.Member_Value <= CDate(@EndDateParam)
)

MEMBER [Measures].[DateValue] AS
[Date].[Date].CurrentMember.Member_Value

// add member to filter out null
// Work Item Count condition 
member hasState as ( iif( ISEMPTY([Measures].[Work Item Count]), 0, 1) )

SELECT
{
   [Measures].[DateValue],
   [Measures].[Work Item Count]
} ON COLUMNS,
{

       [Date Range] *
           [Work Item].[System_State].[System_State].members
 } 
 having [Measures].[hasState] = 1
 ON ROWS
 FROM [Team System]

尽量让事情简单。
只需将 nonEmpty 移出一点:

WITH
SET [Date Range] AS
    Filter(
        [Date].[Date].[Date],
        [Date].[Date].CurrentMember.Member_Value >= CDate(@StartDateParam) AND
        [Date].[Date].CurrentMember.Member_Value <= CDate(@EndDateParam)
    )

MEMBER [Measures].[DateValue] AS
    [Date].[Date].CurrentMember.Member_Value

SELECT
{
    [Measures].[DateValue],
    [Measures].[Work Item Count]
} ON COLUMNS,
{
    NonEmpty(
       [Date Range]
       * [Work Item].[System_State].[System_State]
      ,[Measures].[Work Item Count]
      )
} ON ROWS
FROM [Team System]

编辑

@George posted 了一个有趣的方法。他使用了辅助措施,然后将其输入 HAVING 子句。此子句速度很快,应尽可能使用,但我认为创建新度量的开销抵消了 HAVING 的性能增益。因此不妨保持简单并使用 NonEmpty..

我已经使用类似于 Chris Webb 在 2006 年 post 中的脚本的简单示例进行了测试:https://cwebbbi.wordpress.com/2006/01/04/the-having-clause/

--takes 17 secs
WITH 
  MEMBER [Measures].[hasQuant] AS 
    IIF
    (
      IsEmpty([Measures].[Internet Order Quantity])
     ,0
     ,1
    ) 
SELECT 
  [Measures].[Internet Order Quantity] ON 0
 ,{
      [Date].[Date].MEMBERS*
      [Product].[Subcategory].MEMBERS*
      [Geography].[Country].MEMBERS*
      [Customer].[Gender].MEMBERS
  } HAVING 
  [Measures].[hasQuant] = 1 ON 1
FROM [Adventure Works];

NonEmpty 只是保持简单:

-- secs 11 secs
SELECT 
  [Measures].[Internet Order Quantity] ON 0
 ,NonEmpty
  (
      [Date].[Date].MEMBERS*
      [Product].[Subcategory].MEMBERS*
      [Geography].[Country].MEMBERS*
      [Customer].[Gender].MEMBERS
   ,[Measures].[Internet Order Quantity]
  ) ON 1
FROM [Adventure Works];