MDX : Non Empty 和 NonEmpty
省略若干字....
我最喜欢的 MDX问题是Empty 和Non Empty 的区别,因为尽管很多人平时都用它们来去除查询结果中的 Nulls 值,但是只有少数人理解它们的含义。 好多次我都得到类似 “Non Empty之间有空格,而 NonEmpty 没有”这样的答案。本文的目的在于澄清两者之间的区别。
假设初始的查询是:
SELECT
{
[Measures].[Hits]
,[Measures].[Subscribers]
,[Measures].[Spam]
} ON COLUMNS
,{
[Geography].[Country].Children
} ON ROWS
FROM [Blog Statistics];
结果如下:
NON EMPTY
Non Empty 是定义为轴的集合的前缀, 用于去除 Nulls, 让我们看看在Rows 轴使用了Non empty 后会发生什么。
SELECT
{
[Measures].[Hits]
,[Measures].[Subscribers]
,[Measures].[Spam]
} ON COLUMNS
,NON EMPTY
{
[Geography].[Country].Children
} ON ROWS
FROM [Blog Statistics];
结果如下:
正如你所看到的Chile(CL)已经被过滤了,而UK,Canada等仍然在,即使它们的某些度量也有Nulls。简言之,只有集合定义的行中的所有列成员都为Nulls的行被过滤。这是因为Non Empty 操作符在查询的最高级起作用。 在内部,作为轴定义的集合最先被生成,然后是有Null值的元组被移除。现在我们知道了 Non Empty 是如何工作的,那么说出下面查询的结果也不是什么难事。
SELECT
NON EMPTY
{
[Measures].[Hits]
,[Measures].[Subscribers]
,[Measures].[Spam]
} ON COLUMNS
,{
[Geography].[Country].Children
} ON ROWS
FROM [Blog Statistics];
结果如下:
NONEMPTY()
NonEmpty 返回指定集合中的非空元组的集合, 基于特定集合和另一个集合的交集。假设我们想看到所有与国家相关的有人订阅的度量。
SELECT
{
[Measures].[Hits]
,[Measures].[Subscribers]
,[Measures].[Spam]
} ON COLUMNS
,{
NonEmpty
(
[Geography].[Country].Children
,[Measures].[Subscribers]
)
} ON ROWS
FROM [Blog Statistics];
结果如下:
正如你所看到的, NonEmpty 操作符返回所有行中无null值的订阅者,并且在列中显示所有度量值。NonEmpty 的值是在集合定义该轴时指定的,在这个时候并没有牵扯其它轴,下面的例子可能更好理解。
查询如下:
SELECT
{[Date].[Month].[March]} ON COLUMNS
,{
[Geography].[Country].Children
} ON ROWS
FROM [Blog Statistics]
WHERE
[Measures].[Hits];
结果如下:
稍微想一下猜一下如果NonEmpty 应用在行上结果是什么样的。
SELECT
{[Date].[Month].[March]} ON COLUMNS
,{
NonEmpty([Geography].[Country].Children)
} ON ROWS
FROM [Blog Statistics]
WHERE
[Measures].[Hits];
如果你觉得只显示 IN, US, GB 和 AU, 请回去再读一遍,如果你回答除了Chile外所有行都出现你就是满分,你是个细心的阅读者。原因是NonEmpty 是在集合定义轴的时候确定的,这里的轴是Country,在确定轴的时候,NonEmpty 是基于Date的默认成员(All)为Country的每一个成员评价出来的,CA和AP已经在其它月有数据了,因此CA和AP仍会出现。
使用NonEmpty优化Non Empty
现在你已经知道Non Empty 和 NonEmpty 内部是怎么工作的,我们可以使用这些知识优化查询。假设周中有个复杂的逻辑比如说查找每个月点击量都超过30的所有国家。
查询如下:
SELECT
{[Measures].[Hits]} ON COLUMNS
,{
Filter
(
[Geography].[Country].Children
*
[Date].[Month].Children
,
[Measures].[Hits] > 30
)
} ON ROWS
FROM [Blog Statistics];
在我的维度中有10年的数据,也就是大约120个月属性成员,Country 属性有100个成员。即使我只有10个国家3个月的点击数据,这个条件函数会需要遍历所有国家和月的组合(120* 100). 这样,我们只能用如下查询使用NonEmpty操作符把组合数以减少到30(10*3)以下
SELECT
{[Measures].[Hits]} ON COLUMNS
,{
Filter
(
NonEmpty
(
[Geography].[Country].Children
*
[Date].[Month].Children
,[Measures].[Hits]
)
,
[Measures].[Hits] > 30
)
} ON ROWS
FROM [Blog Statistics];