03.08 理解变量
学会使用变量对于使用DAX非常重要,因为变量提高了代码可读性和公式的性能
可以作为优化技术使用。
初识变量
编写DAX表达式时,可以通过使用变量避免重复书写相同的表达式。例如,我们来看下面这个表达式:VAR Denominator =SUMX(Sales, Sales[SalesAmount]+ Sales[TotalProductCost])VAR Numerator =SUM(Sales[SalesAmount])RETURNDIVIDE(Numerator, Denominator)你可以定义许多变量,它们是表达式的局部变量(只对当前表达式生效)。变量对于简化代码非常有用,因为避免了重复相同的子表达式。变量使用惰性计算,这意味着,如果你定义了一个变量,无论出于什么原因,如果没有被使用,那么这个变量将永远不会被计算。如果需要计算,那么计算只会发生一次:后续对变量的调用都将读取先前计算出的值。因此,当你多次使用复杂表达式时,定义变量也可以作为优化技术使用。正如你将在下面看到的,变量使用的是被定义时的计值上下文,不是被调用时的上下文,这个概念非常有用。## 变量与计值上下文
使用变量让代码更易阅读,还可以避免多次重复相同的子表达式,但考虑到它们与计值上下文交互的方式,变量还有一个非常重要的特点,即:变量在被定义的计值上下文中计算,而不在使用它们的环境中计算。当你希望在复杂公式中使用来自之前计值上下文的计算结果时,这个特性会非常有用。我们来看一个例子。假设你想用数据透视表来显示类别,并且对于每个类别,显示高销售额产品的数量。高销售额产品的定义是:一种产品的销售额超过该类别总销售额的10%。你可以在下图看到最终效果。透视表显示了每个类别中有多少高销售额的产品用变量来计算这个度量值很容易,而且使用变量也让公式变得更容易阅读,如下所示:[HighSalesProducts]:=VAR TenPercentOfSales =[SalesAmount]0.1RETURNCOUNTROWS(FILTER(Product,[SalesAmount]>= TenPercentOfSales))这个公式的有趣之处在于,DAX在FILTER迭代的外部计算变量TenPercentOfSales。如果TenPercentOfSales的计算是在迭代时进行的,由于发生了上下文转换,它将计算当前迭代产品10%的销售额,这会使得整个度量值计算错误。相反,DAX在迭代的外部计算了变量,在内部使用它,这样就可以在当前筛选上下文之外引用表达式的值。如果你想在不使用变量的情况下写出同样的度量值,你需要这样写:[HighSalesProductsCalculate]:=COUNTROWS(FILTER(Product,[SalesAmount]>=CALCULATE([SalesAmount],ALL(Product),’Product Category’)0.1))后一种代码更难读懂,因为你需要在迭代函数中重新构建出之前的计值上下文环境,这不是一项容易的任务,即使对于经验丰富的DAX程序员也是如此。实际上,你将会在理解筛选上下文中了解到此表达式的所有知识,在那里,我们将揭示筛选上下文的所有细节。## 小测试
下面两个度量值在相同的环境中计值,它们的结果一样吗?Measure A =CALCULATE([Total Sales],Color[Color]=”White”)
Measure B = VAR TotalSales =[Total Sales]RETURNCALCULATE(TotalSales,Color[Color]=”White”)注意两个度量值在相同环境中计值,我们假设报表中没有其他筛选器,度量值A的结果是白色产品的总销售额,度量值B的结果是所有产品的总销售额,忽略Color[Color]=”White” 这个筛选条件,原因正是文章中提到的:变量在被定义的计值上下文中计算,而不在使用它们的环境中计算。度量值B的变量定义在没有筛选器的环境中,所以计算了所有产品的销售额,即使它在接下来的CALCULATE中调用,结果也不再变化。这个描述看似简单,但仍然需要你反复理解。如果你发现可以使用变量来简化计算,比如代替计值上下文中的EARLIER,那么我们很高兴地欢迎你加入DAX高手的行列。如果没有,不要担心。这种情况对于第一次阅读的新人是很正常的。接下来仍有许多内容专门介绍这些复杂的知识,它们将帮助你获得掌握计值上下文所需的技能 订阅本文评论 最新最旧得票最多成员136**6402Follow this user#637以我当前的理解能力来说我觉得小测试里的两个结果是一样的,var只是单纯的暂时存储,类似对变量赋值,return有点像是一种标识符或信号,表示我接下来要开始用变量了.赞0踩 回复10 天 之前作者高飞Follow this user#638变量是一次计值,反复调用,不受调用环境的计值上下文影响,所以测试题目的答案是不一样,具体分析可以见正文最后赞0踩 回复9 天 之前成员ding_ye_timoFollow this user#602答案根据上下文的具体内容而定,不一定一样赞0踩 回复16 天 之前作者高飞Follow this user#603这里的预设是两个度量值在相同的环境里计值赞0踩 回复16 天 之前成员pearlzhangFollow this user#595小测试作答:结果不一定一样,度量值不一样。我理解:定义的变量是所在的筛选上下文起作用;不迭代行上下文。赞0踩 回复17 天 之前作者高飞Follow this user#596如果整个模型只有白色一种颜色结果是一样的,不过这属于脑筋急转弯,不是题目要考察的内容。当你在计算列里定义变量的时候,是会考虑行上下文的赞1踩 回复17 天 之前成员pearlzhangFollow this user#598在计算列中使用定义变量,只计值定义的当前行的值,get了。赞0踩 回复16 天 之前作者高飞Follow this user#599“只计值定义的当前行的值” 也过于绝对,如果发生上下文转换,变量是可以计值模型的其他表的 赞1踩 回复16 天 之前