从数据到信息
从信息到洞察

理解 FIRSTNONBLANK 和 LASTNONBLANK

FIRSTNONBLANK / LASTNONBLANK 扫描一个表,逐行计算第二参数,并返回不为空的第二参数所对应的表的最后一个/第一个值。与 MIN/MAX 不同的是,它们可以根据你指定的逻辑进行计算,且支持文本格式。

FIRSTNONBLANK / LASTNONBLANK

FIRSTNONBLANK ( < ColumnName>, < Expression> )
LASTNONBLANK ( < ColumnName>, < Expression> )

<ColumnName>在当前筛选上下文中每行计值<Expression>,返回结果不为空的第一个或最后一个<ColumnName>的值。其行为类似于 SUMX 或其他类似函数,因为它们都是迭代函数:为列参数设置行上下文,然后使用该行上下文计值表达式。

第一参数直接引用列名,不需要借助任何表函数,因为它等价于:

CALCULATETABLE ( DISTINCT ( <ColumnName> ) )

如何判定第一个值和最后一个值

  • 当<ColumnName>是文本格式时:
    首字母顺序对第一参数的结果进行排序,FIRSTNONBLANK 返回升序排序的第一个值, LASTNONBLANK 返回最后一个值
  • 当<ColumnName>是数字格式时:
    数值顺序对第一参数的结果进行排序,FIRSTNONBLANK 返回升序排序的第一个值, LASTNONBLANK 返回最后一个值
  • 当<ColumnName>是日期时间格式时:
    时间顺序对第一参数的结果排序,FIRSTNONBLANK 返回升序排序的第一个值, LASTNONBLANK 返回最后一个值

对新手来说FIRSTNONBLANK / LASTNONBLANK 最容易混淆的地方是它返回的并不是<Expression>的第一个和最后一个值,而是<Expression>对应的<ColumnName>的第一个和最后一个值。如果你感兴趣的是此时<Expression>的结果,可以使用 FIRSTNONBLANKVALUE / LASTNONBLANKVALUE

最后,FIRSTNONBLANK / LASTNONBLANK 的第一参数经常使用日期列,这使得它在时间智能函数中经常出现,但实际上它支持任何类型的列,因为这两个函数本质上都是迭代函数

示例表:Table

以上图中 Table 的数据为例,如果想要获得销售额不为空的第一个产品经理,有两种写法:

F1 = FIRSTNONBLANK('Table'[地区经理],CALCULATE(SUM('Table'[销售额])))
F2 = FIRSTNONBLANK('Table'[地区经理],SUM('Table'[销售额]))

F1 得到了正确的结果「楚杰」,

F2 的结果是「白德伟」,原因在于 F2 公式中的SUM('Table'[销售额])忽略行上下文,每行计值的结果相同,使得 FIRSTNONBLANK 在整个经理列表中计算最小值,得到了错误的结果。

在这个示例中,如果你想要返回楚杰对应的销售额,最简单的写法是使用 FIRSTNONBLANKVALUE

迭代函数的上下文转换

如果<Expression>和<ColumnName>共用同一张表的数据,不需要特别处理就可以正常计值。但是当<Expression>使用<ColumnName>所在表以外的其他表时,你必须通过使用 RELATEDTABLECALCULATETABLECALCULATE 进行上下文转换。这是所有与日期相关的计算的最佳实践,而且每次使用单独的日期表时这种情况都很常见。比如要正确地获得给定度量值或表的最后一个非空日期值,你必须使用如下表达式:

LASTNONBLANK ( Dates[Date], CALCULATE ( COUNT ( Inventory[Quantity] ) ) )

它返回在当前筛选上下文中,库存表数量列不为空的最近日期,你也可以用另一个等价公式:

LASTNONBLANK ( Dates[Date], COUNTROWS ( RELATEDTABLE ( Inventory ) ) )

这个表达式返回当前筛选上下文中,库存表中有相关记录的最后一个日期。

可用作 CALCULATE 筛选器的表函数

FIRSTNONBLANK 和 LASTNONBLANK 返回标量值,但同时也可以作为 CALCULATE 函数的筛选器参数,因为本质上它们返回的是单行表。比如:

Units LastNonBlank :=
    CALCULATE (
        SUM ( Inventory[UnitsBalance] ), 
        LASTNONBLANK (
            'Date'[Date],
            CALCULATE ( SUM ( Inventory[UnitsBalance] ) )
        )
    )

LASTNONBLANK 与 LASTDATE 的区别

FIRSTNONBLANK/LASTNONBLANK 函数接受任何数据类型作为其第一参数,而 FIRSTDATE/LASTDATE 函数则需要列必须使用日期类型。如果日期值所在的列使用了另一种数据类型,你希望获得它在筛选上下文中的第一个或最后一个值时,需要使用 FIRSTNONBLANK/LASTNONBLANK 而不是 FIRSTDATE/LASTDATE,将任何非空表达式作为第二个参数传递。当然,你也可以考虑在这种情况下使用 TOPN 函数。

TopDate := 
TOPN (
    1, 
    VALUES ( Date[DateKey] ), 
    [Internet Total Sales] 
)

如果两个或两个以上的日期具有相同的最高销售额,则 TopDate 度量值将报错,因为 TOPN 返回了一个包含一列和两行或更多行的表,不能被转换为标量值。你可以对公式做如下改动:

TopDate := 
LASTNONBLANK (
    TOPN (
        1, 
        VALUES ( Date[DateKey] ), 
        [Internet Total Sales]
    ), 
    1 
)

理解 LASTNONBLANK 的第二参数

本文隐藏内容查看价格为1G币,请先
注:加入VIP会员可享受全站权益,性价比更高。单独购买的内容长期有效,不受时间限制。

排序规则

如上文所述,你可以对任何数据类型的列使用 FIRSTNONBLANK 和 LASTNONBLANK,但是需要注意数值和文本类型的排序规则有所不同。

本文隐藏内容查看价格为1G币,请先
注:加入VIP会员可享受全站权益,性价比更高。单独购买的内容长期有效,不受时间限制。

17
说点什么

1000
 
鼓掌微笑开心憧憬爱你色并不觉得吃瓜doge二哈喵喵思考笑哭捂脸悲伤大哭抓狂汗偷笑打脸捂眼黑线问号晕拜拜闭嘴衰咒骂ok作揖
7 评论数
10 被回复的评论
8 订阅评论的人数
 
查看最近回复
查看最热评论
  订阅本文评论  
最新 最旧 得票最多
提醒
成员
奇缘

老师,”在 TopDate 公式的第二种写法中,LASTNONBLANK 使用了一个常数 1 作为第二参数”. 这里实际上面用的是FIRSTNONBLANK,可能写错了。

成员
teamowu

老师,为什么这个按案例来,度量值结果返回的是杨戬(Y)不是楚杰(C)?

ALL.png
成员
wxb2012

感谢老师之前的回复
以下是我今天的理解请老师看一看是否正确
F1 = FIRSTNONBLANK(‘Table'[地区经理],CALCULATE(SUM(‘Table'[销售额])))
白德伟成为最后一个的原因是,第二参数CALCULATE(SUM(‘Table'[销售额])在百德伟这一行的行上下文计值为空,所以百德伟被跳过,选择首字母为C的楚杰。
而F2 = FIRSTNONBLANK(‘Table'[地区经理],SUM(‘Table'[销售额]))
百德伟成为第一的原因是,第二参数SUM(‘Table'[销售额])忽略了百德伟这行的行上下文并且计值为销售额的总和,即使白德伟销售额为空也不影响他的排序,所以首字母为B排位最高的白德伟成为第一个。
我的理解是,先进行排序,再看第二参数在行上下文的作用下计值是否为空,如果本来排在首位的计值为空则被跳过,选第二个,第二个还是为空选第三个,以此类推。

成员
mepub

F1 = FIRSTNONBLANK(‘Table'[地区经理],CALCULATE(SUM(‘Table'[销售额])))
这个表达式,第二个参数是不是等于没发挥作用?

成员
mepub

只是将空值排除了?

成员
Truman

为什么F2中“白德伟”变第一个了,所有销售额不应该都是一样的吗?

游客
new4w

这个网站是知识含量最高的!

成员
150

请问下,示例中,F1 = FIRSTNONBLANK(‘Table'[地区经理],CALCULATE(SUM(‘Table'[销售额])))返回的结果,为何不是最小记录:杨健?

DAX 圣经

导读

初识 DAX

DAX 基础知识

DAX 原理

DAX 高级原理

基础函数类型

迭代函数

CALCULATE 函数

CALCULATE 调节器

基础表函数

条件判断函数

查找匹配函数

时间智能函数

统计类函数

投影函数

分组/连接函数

集合函数

其他函数