DAX的正确计算依赖于上下文,除了前面介绍的筛选上下文,还有一种上下文类型是行上下文。
尽管行上下文和筛选上下文都是计算上下文,但二者却是不同的概念,筛选上下文就如它的名字一样,目的是对表进行筛选。而行上下文却不是用来筛选表的,而是用来对表内容(也就是行)进行迭代并获取出其中的列值的。
比如新建计算列用来计算毛利润:
Sales[Gross Margin]= Sales[Quantity]* ( Sales[Net Price]- Sales[Unit Cost])
因为公式中参与计算的三列在每一行都有不同的值,自然的,最终结果也会计算产生不同的值。与筛选上下文类似,这是因为某个计算上下文的存在。这一次,上下文环境没有筛选表,而是识别计算发生时所在的行。
我们知道一个计算列是逐行计算,但 DAX 是如何得知它正在迭代的是哪一行的?这是由另外一种计算上下文所规定的——行上下文。当我们在一张有100万行的表上创建一个计算列时,DAX创建了一个行上下文,使用行上下文作为光标来逐行迭代表并计算结果。
当我们创建一个计算列,DAX 默认自动创建行上下文,无需再手工创建:计算列的计算永远在行上下文中执行。你已经了解到如何手工创建行上下文——迭代。事实上,我们可以以度量值的形式编写毛利润,如下面的代码所示:
Gross Margin :=
SUMX (
Sales,
Sales[Quantity]* ( Sales[Net Price]- Sales[Unit Cost])
)
在此例中,由于是度量值,不存在自动的行上下文。SUMX 作为迭代器,创建了一个行上下文开始逐行对 Sales 表进行迭代。在迭代过程中,它在行上下文中执行 SUMX 的第二个表达式。所以,在迭代的每一步,DAX 引擎都知道应该使用表达式中三个列的哪个值。
行上下文存在于我们创建的计算列或迭代过程中的计算。不存在其他方式创建行上下文。另外,当我们需要获得某列某行的值时,需要利用行上下文。例如,下面的度量值是非法的。它试图计算 Sales[NetPrice]的值,但是由于行上下文的缺失使得计算时无法得知应采用哪一行。
Gross Margin := Sales[Quantity]* ( Sales[Net Price]- Sales[Unit Cost])
同样的表达式在计算列中执行是合法的,但在度量值中使用会变成不合法的。这并不是因为计算列和度量值有着不同的使用方法,而是因为计算列会自动创建行上下文,而度量值不会。如果想要在度量值中逐行计算该表达式,需要创建行上下文进行迭代。
至此,我们需要强调一个重要的概念:行上下文并非是特殊的筛选上下文而用来筛选某一行。行上下文在任何情况下都不会筛选模型;行上下文仅仅对 DAX 做出指示应该使用表的哪一行。如果要筛选模型,筛选上下文才是正确的工具。换句话说,如果想要逐行计算表达式,行上下文才是正确的选择。
《The Definitive Guide to DAX》学习笔记-节选
采悟 @ PowerBI星球







网友评论