[MDX学习笔记之三]MDX的上下文(Context)

前面的Blog中,我们说要构建Cube或编写MDX,就必须理解Cube的结构。可是当熟悉了Cube结构之后,我们还是会有很多困挠。比如:为何有些需求用MDX语句似乎做不出来?为何有些MDX语句无法输出我们想要的结果(不是抱错就是输出结果错误)?为何有些MDX语句执行起来非常的慢?要想解决这些问题,除了了解Cube结构,我们还必须理解MDX的运行机制,而运行机制的首要概念便是上下文(Context)。以下MDX语句可以在SSAS的示例库:Adventure Works中运行。

上下文(Context)
MDX的运行机制可以用一句话来描述——在Cube结构的基础上,按照一定顺序执行MDX中的不同部分,然后根据不同部分的上下文来计算,最后输出。这里有一个问题:何为MDX的上下文呢?上下文是指在所有维度的Hierarchy上都取一个或多个值构成的区域。请看下图:


上图中的蓝色部分好比整个Cube,而红色区域代表了一个上下文。当然实际的Cube包含多个维度,所以实际的样子会比上图(只有两个维度)复杂得多。

这里插一句话,要理解MDX,我们最好忘掉SQL语句。原因在于:1)SQL语句中的上下文一般只有一个,如果多个的话,一般执行速度将会变得很慢。而MDX语句中一般都包含多个上下文,不同的部分上下文往往不同,执行起来速度很快;2)在关系型的二维结构中,SQL语句中的所有的内容都是明确指定的(所有的列和表等),而在MDX语句中,除了明确指定外,很多内容实际是隐含指定的,这些指定在不同语句中可能会给被传递或改写,这就是MDX语句的复杂之处,这也是就是MDX和SQL的最大区别,这同时也是为什么有些需求只能用MDX语句来实现的原因,比如:同比、环比、移动平均、KPI等。

为了加深对上下文的认识,让我们来看一看下面的语句——计算每种产品的平均每天的销售额。

WITH MEMBER [Measures].[Average Internet Sales Amount] AS 
AVG(DESCENDANTS([Date].[Calendar].CurrentMember, [Date].[Calendar].[Date],SELF), 
[Measures].[Internet Sales Amount])
SELECT 
{
[Measures].[Internet Sales Amount],[Measures].[Average Internet Sales Amount]ON 0,
NON EMPTY 
[Product].[Product Categories].[Product Name].Members ON 1
FROM [Adventure Works]

上面这段MDX语句能够正常的计算出结果,但是,如果我们加上一些限定,比如:计算每种产品在2002年和2003年的平均每天的销售额。
WITH MEMBER [Measures].[Average Internet Sales Amount] AS 
AVG(DESCENDANTS([Date].[Calendar].CurrentMember, [Date].[Calendar].[Date],SELF), 
[Measures].[Internet Sales Amount])
SELECT 
{
[Measures].[Internet Sales Amount],[Measures].[Average Internet Sales Amount]ON 0,
NON EMPTY 
[Product].[Product Categories].[Product Name].Members ON 1
FROM [Adventure Works]
WHERE
{
[Date].[Calendar].[Calendar Year].&[2002][Date].[Calendar].[Calendar Year].&[2003]}

上面的MDX语句的输出结果中会出现很多#error,其原因在于:在[Measures].[Average Internet Sales Amount]的当前上下文中,由于[Date].[Calendar]仅包含两个成员(即2002年和2003年),所以MDX解析器无法确定哪一个成员是CurrentMember。要想解决这个问题,其中的一个办法是使用Existing,详见下文:
WITH MEMBER [Measures].[Average Internet Sales Amount] AS 
AVG(EXISTING [Date].[Calendar].[Date]
[Measures].[Internet Sales Amount])
SELECT 
{
[Measures].[Internet Sales Amount],[Measures].[Average Internet Sales Amount]ON 0,
NON EMPTY 
[Product].[Product Categories].[Product Name].Members ON 1
FROM [Adventure Works]
WHERE
{
[Date].[Calendar].[Calendar Year].&[2002][Date].[Calendar].[Calendar Year].&[2003]}


上面的语句中EXISTING [Date].[Calendar].[Date]表示当前上下文中包含的[Date].[Calendar].[Date],所以能够得到正确的结果。

总结
本文简单介绍了MDX的运行机制中的上下文的概念,它是理解MDX的关键概念之一。要深入一些的话 有兴趣的朋友可以看看Mosha Pasumansky的文章:http://www.sqljunkies.com/WebLog/mosha/archive/2006/11/01/slicer_axis_interaction.aspx
http://www.sqljunkies.com/WebLog/mosha/archive/2006/11/12/slicer_axis_interaction_deep_exists.aspx
http://www.mosha.com/msolap/articles/mdxmultiselectcalcs.htm

posted on 2006-11-26 08:43  microsheen  阅读(5178)  评论(22编辑  收藏  举报