代码改变世界

MDX Step by Step 读书笔记(五) - Working with Expressions (MDX 表达式) - CurrentMember - Properties - Existing 的使用

2013-04-19 15:48  BIWORK  阅读(5234)  评论(5编辑  收藏  举报

Current Member  当前成员

在计算成员中会经常用到获取当前对象的函数, 可以这样来访问 [Dimension].[Hierarchy].CurrentMember

但是要注意这个函数返回的仅仅是一个成员的引用,一般要通过访问成员的某些属性来获取一些具体的值。

    

示例一 - 访问当前成员和父成员

WITH
MEMBER [Measures].[Current Member Name] AS
    [Product].[Product Categories].CurrentMember.Name

MEMBER [Measures].[Parent Member Name] AS
    [Product].[Product Categories].CurrentMember.Parent.Name

MEMBER [Measures].[Current Member Name NULL] AS
    [Product].[Product Categories].CurrentMember

MEMBER [Measures].[Parent Member Name NULL] AS
    [Product].[Product Categories].CurrentMember.Parent

SELECT
{
            ([Measures].[Current Member Name]),
            ([Measures].[Parent Member Name]),
            ([Measures].[Current Member Name NULL]),
            ([Measures].[Parent Member Name NULL])
} ON COLUMNS,
{[Product].[Product Categories].AllMembers} ON ROWS
FROM [Step-by-Step]

查询结果

最后两列的值都是为 NULL, 是因为无论是 CurrentMember 还是 CurrentMember.Parent 返回的只是一个引用,要得到具体的值就应该在引用的时候加上一些属性。

CurrentMember 返回的是当前的成员

CurrentMember.Parent 返回的是当前成员的父成员引用

在这个例子中可以看到这些成员的父成员,除了 All Products 外,因为对于 All Products 来说它没有父成员,所以显示为 null。

 

MEMBER.Properties 函数的使用

Properties 可以帮助通过名称返回一个成员固有的或者用户自定义的属性内容。一般情况下是以字符串形式返回,除了指定了 TYPED 关键字,那么将按照这个属性本身的数据类型来返回数据。

member.Properties( Name [, TYPED] )

下面列表中列出了 SSAS 自带的成员属性 

示例二 使用 Properties

WITH
MEMBER [Measures].[Parent Member Name] AS
[Product].[Product Categories].CurrentMember.Properties("LEVEL_NUMBER") 

SELECT
{([Measures].[Parent Member Name])} ON COLUMNS,
{[Product].[Product Categories].AllMembers} ON ROWS
FROM [Step-by-Step];

按照之前的图例解释 LEVEL_NUMBER 返回的是这个成员在属性层次结构中的位置,根成员的Level 为0。

查询结果 –

示例三  使用 IIF 条件语句

使用IIF 表达式很简单,和我们在其它变成语言中学习的 if 条件语句使用相同

下面示例查询所有的 Product 成员并显示它们的父成员,由于根Level的成员没有父成员,因此根成员的父成员将被显示为 “Not Applicable”

WITH
MEMBER [Measures].[Parent Member Name] AS
IIF(
    [Product].[Product Categories].CurrentMember.Properties("Level_Number",TYPED)=0,
    "Not Applicable",
    [Product].[Product Categories].CurrentMember.Parent.Name
)

SELECT
{([Measures].[Parent Member Name])} ON COLUMNS,
{[Product].[Product Categories].AllMembers} ON ROWS
FROM [Step-by-Step];

查询结果

示例四 继续使用 IIF 条件 

WITH
MEMBER [Measures].[Parent Member Name] AS
IIF(
    [Product].[Product Categories].CurrentMember.Properties("Level_Number",TYPED)=0,
   "Not Applicable",
   [Product].[Product Categories].CurrentMember.Parent.Name
)

MEMBER [Measures].[Percent of Parent] AS
  ([Measures].[Reseller Sales Amount])/
  ([Product].[Product Categories].CurrentMember.Parent, [Measures].[Reseller Sales Amount])
  ,FORMAT_STRING="Percent"

SELECT
{
    ([Measures].[Parent Member Name]),
    ([Measures].[Reseller Sales Amount]),
    ([Measures].[Percent of Parent])
} ON COLUMNS,
{[Product].[Product Categories].AllMembers} ON ROWS
FROM [Step-by-Step];

第一点要注意的是如何引用一个父类成员 [Product].[Product Categories].CurrentMember.Parent

而不是之前的例子中[Product].[Product Categories].CurrentMember.Parent.Name, 请一定分清父成员和父成员属性的区别。

第二点当父成员为 NULL 的时候,整个元组 ([Product].[Product Categories].CurrentMember.Parent, [Measures].[Reseller Sales Amount])也为NULL,但是在除法运算中将被替换为0 ,分母为0,运算出错。但是注意,这里的 NULL 分为两种情况,一种是真正的NULL,不存在这个值转换为0;一种是因为没有值显示为NULL,那么最后计算的结果也显示为 NULL。

加上对父成员级别的判断

WITH
MEMBER [Measures].[Parent Member Name] AS
IIF(
    [Product].[Product Categories].CurrentMember.Properties("Level_Number",TYPED)=0,
    "Not Applicable",
    [Product].[Product Categories].CurrentMember.Parent.Name
)

MEMBER [Measures].[Percent of Parent] AS
IIF(
    [Product].[Product Categories].CurrentMember.Properties("Level_Number",TYPED)=0,
    "Not Applicable",
    ([Measures].[Reseller Sales Amount])/
    ([Product].[Product Categories].CurrentMember.Parent,
    [Measures].[Reseller Sales Amount])
)
,FORMAT_STRING="Percent"

SELECT
{
    ([Measures].[Parent Member Name]),
    ([Measures].[Reseller Sales Amount]),
    ([Measures].[Percent of Parent])
} ON COLUMNS,
{[Product].[Product Categories].AllMembers} ON ROWS
FROM [Step-by-Step]

查询结果

除了 CurrentMember 以外,Analysis Services 还支持其它的一些行数来访问一些比较特别的成员。

[Dimension].[Hierarchy].DefaultMember

[Dimension].[Hierarchy].UnknownMember

[Dimension].[Hierarchy].DataMember

DefaultMember 函数返回一个给定层次结构的默认成员。如果没有定义默认成员,那么就返回All这个成员,如果没有All这个成员,就返回层次结构中第一个成员。

UnknownMember 函数返回指定的层次结构中未知的成员。如果不存在这种 unknown 成员,那么就返回 null。但是在度量值层次结构中使用 UnknownMember,就返回一个 error,因为在度量值层次结构中不应该存在 unknown 成员这种概念。 

DataMember 返回系统生成的数据成员,它与某个维度的非叶成员相关联。

 

在表达式中使用 SET 集合

在表达式中使用 SET 集合要注意,SET 集合不会被当前单元格的上下文所影响。这样一来,Auto-Exists 机制就无法应用,先来看一个例子。

WITH
MEMBER [Measures].[Number of Products] AS
COUNT(
            [Product].[Product].[Product].Members
)

SELECT
{
            ([Measures].[Reseller Sales Amount]),
            ([Measures].[Number of Products])
} ON COLUMNS,
{[Product].[Category].Members} ON ROWS
FROM [Step-by-Step]

查询结果

 

按照我们之前的理解, 在计算 Category 下面有多少个Products时,Auto-Exists 会自动归类匹配,但是实际上 Products 集合在计算成员总数的时候并没有关联到计算成员中的Tuple的上下文环境,因此算出来的总数就是实际所有 Product的总数 397。

使用 Existing 关键字可以强制在计算成员表达式中的 SET 使用当前上下文环境。

WITH
MEMBER [Measures].[Number of Products] AS
COUNT(
EXISTING [Product].[Product].[Product].Members
)

SELECT
{
    ([Measures].[Reseller Sales Amount]),
    ([Measures].[Number of Products])
} ON COLUMNS,
{[Product].[Category].Members} ON ROWS
FROM [Step-by-Step];

可以这样理解,在依次与 Product.Category 层次结构下的各个成员交汇的时候,那么这些成员就限定了计算成员中 Products 统计成员个数的空间。

比如说,当前读取的 Category 成员是Bikes,那么在应用了 Existing 关键字后,可以认为所有的关于 Products 下的 Members 的统计实际上都限定在了 Bikes 这个大类下面来进行了,Bikes 就是它们的上下文环境,其实这就是 Auto-Exists 的作用。

更多 BI 文章请参看 BI 系列随笔列表 (SSIS, SSRS, SSAS, MDX, SQL Server)  如果觉得这篇文章看了对您有帮助,请帮助推荐,以方便他人在 BIWORK 博客推荐栏中快速看到这些文章。