DAX从入门到精通 4-3-1 使用earlier函数

使用earlier函数

你可能认为,在行上下文中对同个表格进行多次嵌套是非常少见的。实际上,这个情况经常发生。我们看下下面这个例子。设想你想计算,针对每个产品,有多少个其他的产品价格是高于该产品的。这个需要对产品的价格进行排序。
要解决这个问题,我们使用filter函数,这个函数我们之前使用过。回忆一下,filter使用迭代计算,对表的所有行进行计算,然后返回一个仅包含符合条件的行的表。例如,你要筛选大于100元的产品。可以这样写:

= FILTER ( Product, Product[UnitPrice] > 100 )

回到刚才那个案例:建立了计算列,然后计数所有单价大于当前行产品单价的产品。如果你称当前产品价格为 PriceOfCurrentProduct。那么我们可以很容易的写出我们需要的计算:

Product[UnitPriceRank] =
COUNTROWS (
FILTER (
Product,
Product[UnitPrice] > PriceOfCurrentProduct
))

filter返回了那些价格高于当前产品价格的记录,然后返回计数结果。剩下的问题就是如何表达当前的产品,用这个来代替PriceOfCurrentProduct。当前行,也就是DAX用于计算的行的金额,这个表达式的写法,比你设想的会难一些。
我们在Product表中定义了计算列,所以,DAX会创建一个行上下文来迭代。但是,表达式使用了filter函数在同一个表也创建了行上下文。事实上,在第五行使用的Product[UnitPrice]的值就是当前行的值。这个情况下,新的行上下文会隐藏旧的行上下文,所以说,你要使用的是当前单元格所在行的值而不是最后行上下文生成的值。也就是你要使用的是上一次的行上下文,也就是计算列生成的。
DAX提供了一个函数,使得整个需求变的可能:earlier。它可以提取之前一个行上下文生成的列的值,而不是最后的一个。所以,PriceOfCurrentProduct可以使用Earlier(product[unitprice])。
earlier是DAX中最奇特的一个函数,许多学生对Earlier感到陌生,因为没有从行上下文的角度思考,以及没有考虑导可以在同一个表格中,嵌套了两个行上下文。事实上,EARLIER是很简单函数,很多情况下都可以使用,下面整个代码可以解答我们的需求:

Product[UnitPriceRank] =
COUNTROWS (
FILTER (
Product,
Product[UnitPrice] > EARLIER ( Product[UnitPrice] )
))
+ 1

下图可以看到在Product表定义了计算列,使用了Unit Price作为关键字降序排列


image.png

因为有14个产品的价格一样,所以它们的排名都是1,第15个产品的排序是15,同价格的产品排名也是15。我们强烈的建议你认真的学习这个小的案例,因为它能很好的检测你对行上下文的理解和使用,如何使用filter建立,以及使用earlier获取之前的行上下文结果。

笔记
earlier可以接受第二个参数,用来代表要跳过多少次之前的上下文,所以你可以跳过2次或者3次。另外,还有个earliest可以使你直接获取导最外层的行上下文。但是,通常情况下,earlier和earliest的第二个参数都是极少用到的。因为嵌套两次行上下文的情景非常常见,但是3次及以上的情况就非常少遇到了。

在结束这个案例之前,还可以再说点,例如你想把值的排序转成另外一种排序的方式,按价格而不是按产品。这里,我们可以使用values函数,之前章节我们有学过。

Product[UnitPriceRankDense] =
COUNTROWS (
FILTER (
VALUES ( Product[UnitPrice] ),
Product[UnitPrice] > EARLIER ( Product[UnitPrice] )
))
+ 1

我们可以看看新创建的计算列


image.png

我们强烈的建议你认真的把earlier函数学习一遍,因为它非常的常用。不过,作为替代方案,我们还可以使用变量。使用变量可以是代码更容易阅读。例如,之前的需求可以用这个表达式来书写:

Product[UnitPriceRankDense] =
VAR
CurrentPrice = Product[UnitPrice]
RETURN
COUNTROWS (
FILTER (
VALUES ( Product[UnitPrice] ),
Product[UnitPrice] > CurrentPrice
))
+ 1

这个代码中,我们使用了变量,我们把当前的价格存储再了CurrentPrice变量中,然后在后面的对比中使用它。给变量一个名称可以使得代码更容易阅读,而不是每次阅读的代码的时候,都要在一堆的代码中重新检查代码的逻辑。

你可能感兴趣的:(DAX从入门到精通 4-3-1 使用earlier函数)