第四章 学习上下文
到本书的这个位置,你已经学习了DAX的基础知识。你知道了如何创建计算列和度量值,你对使用DAX书写的函数有了很好的认识。本章,我们要把我们的能力推向一个新的层次,在掌握了牢靠的DAX语言理论基础后,你会成为一个真正的DAX选手。
以你目前掌握的知识,你已经可以创建许多有趣的报表了。但是你还是需要学习DAX的上下文概念,以便创建一些更加复杂的报表。上下文概念是所有DAX高级功能的基础。
这里我要给学习的朋友一些建议。上下文概念看起来很简单,通过一段时间的学习,很快就能基本的了解和知道它的作用。但是,对于一些细节难以察觉的地方,你需要仔细的思考,确保完全的理解。否则,在DAX的学习过程中的某个点,你就会感到疑惑。在公开的和私下的课程中,我教过许多学生。我们知道这种情况是非常普遍的。有时候,你会觉的公式的运作就像魔术一样,它能计算出希望的结果,但是你不明白它是如何工作的。别担心,这个不仅仅是你会遇到,大部分人都会遇到这样的问题。这说明,上下文的概念它们没有完全掌握。解决方法就是,很简单,回退导这个章节,重新的阅读一次,你就会发现一些你之前没有注意到的细节。
进一步,上下文概念对于calculate函数的正确是非起到非常关键的作用,而calculate可能是功能最强大,最难以掌握的DAX函数。在第五章中,我们会介绍calculate函数,然后本书剩余部分中,都会有它的使用案例。没有坚实的上下文理论基础,而想要使用calculate是不可能的,反过来说,想要学习好上下文的概念,而不通过calculate函数的使用,也是几乎不能的。因此,本章节就是使用两者交叉学习,来掌握它们。按照我们的经验,本章节,是值得您标注为重点的。
上下文简介
首先介绍一下什么是上下文,任何有个表达式都是由其所在的上下文决定的 ,也就是它所处的位置。例如下面这个简单的度量值:
[Sales Amount] := SUMX ( Sales, Sales[Quantity] * Sales[UnitPrice] )
你已经懂得这个公式的意思:计算sales表中,所有quantity和unitprice乘积的求和。我们把度量值放到透视表中,看下结果:
仅仅这一个数字,看起来没有什么意义。但是,如果你仔细思考,这个函数真的是按我们预期的进行计算:销售额的总值,一个非常大的数字,但是没有什么含义。但是当我们在透视表引入更多的行,对总值进行切片的时候,一些有趣的事情发生了。例如,可以把product color拖到行,透视表就变得不一样了:
总计还存在,但是现在还同时展示了其他更细的值,而且每个数字都有它的意义。仔细思考一下,函数似乎没有按照我们代码写的这样进行计算。
我们的预期是,函数计算所有销售额的总和,但是在透视表的每一行,函数并没有计算所有销售的总额,它只计算了特定color产品的销售总额。另外,我们也没有特别声明,这个函数可以用于数据模型的某一个数据子集。
为什么函数可以根据不同的单元格计算不同的值呢?答案很简单:DAX会根据当前的上下文进行计算。,可以把上下文理解成围绕单元格所形成的环境。
因为product color在行的位置,每行的数据,都不能看到整个的数据库,只能看到特别颜色部分的数据。整个就是函数所处环境的意思。整个环境的筛选条件,优先于函数的表达式。当函数计算销售额的时候,它不会计算整个数据库,因为函数没办法看到整个库。当DAX计算白色行的时候,函数只能看到白色的部分,也正因为这样,它就只计算白色的产品销售额。
DAX函数都包含一个计算表达式,但是DAX会首先确定计算的范围,整个会影响计算的最终结果。函数可以一样,但是结算的结果会根据单元格所在的位置,而进行不同数据子集的运算。
整个表格只有总计栏是按照公式书写的方式计算的。在总计的级别,没有过滤条件的存在,所以DAX函数可以查询整个数据表。
注意点:
这里我们为了简化,便于理解,使用了透视表作为案例。实际上,还可以在查询中使用上下文,这个后面我们会详细介绍。但是目前阶段,我们建议只要考虑透视表的案例就可以了,用来简化场景,便于我们理解学习。
现在,我们把年放到列上,使得透视表看来更加有趣一些。如下:
这里,我们可以明确了:每个单元格即便是使用的公式一样,但是所得到的值都会不同,因为透视表的行和列,共同定义了上下文。white product 2008年和white product 2007年销售额不同。不仅如此,行和列还可以添加不止一个条件。行列共同决定了上下文。下图可以明显的看出这个:
每个单元格都有不同的值,行级别,有color和brand。行列共同决定了上下文。例如,图中选定的单元格是黑色,contoso,2007年的。
注意:
字段的位置,无论是在行,列,还是切片器,还是页面的筛选器或者其他形式的过滤器。所有这些过滤条件共同决定了上下文,然后应用到DAX函数中。字段放在行或者列,只是给人感官上有影响,但是不会改变DAX的计算结果。
来看下这个图,我们把product category放到切片器,月份在筛选器,月份我们选择12月。
现在,我们已经知道,每个单元格的计算,都是由它所在的行,列,筛选器,切片器组成的上下文共同决定的。所有的这些过滤器优先于函数表达式作用于函数。更重要的一点是,不是所有的单元格都具有相同类型的上下文条件。例如。列的总计栏,只包含了category,month,year,而没有包括color和brand。color和brand处在行的位置,所以并没有对总计实施过滤。对于透视表中颜色的小计,上下文过滤器没有包含厂家,只有包含了color。
我们称这样的上下文为筛选上下文,如它的名字一样,它对表格进行过滤筛选。函数横具其筛选上下文作为依据,计算各个单元格的值。这个计算逻辑,虽然简单易懂,但是,非常值得我们深刻的理解其工作方式。
已经学习了什么是筛选上下文,我们就可以把下面的DAX表达理解为:根据当前筛选上下文计算销售总额。
[Sales Amount] := SUMX ( Sales, Sales[Quantity] *
Sales[UnitPrice] )
后面的阶段,我们会学习如何阅读,修改和清除筛选上下文。但是现在,我们要有个明确的认知,筛选上下文总是对所有的透视表单元格或者报表值/查询起作用。要想完全明白DAX函数的计算就必须对筛选上下文有良好的理解。