[知识体系] 理解 FIRSTNONBLANK 和 LASTNONBLANK

  [复制链接]
查看165639 | 回复148 | 2021-2-21 19:29:53 | 显示全部楼层 |阅读模式
FIRSTNONBLANK / LASTNONBLANK 扫描一个表,逐行计算第二参数,并返回不为空的第二参数所对应的表的最后一个/第一个值。与 MIN/MAX 不同的是,它们可以根据你指定的逻辑进行计算,且支持文本格式。

FIRSTNONBLANK / LASTNONBLANK
  1. FIRSTNONBLANK ( < ColumnName>, < Expression> )
  2. LASTNONBLANK ( < ColumnName>, < Expression> )
复制代码

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


第一参数直接引用列名,不需要借助任何表函数,因为它等价于:
  1. CALCULATETABLE ( DISTINCT ( <ColumnName> ) )
复制代码
如何判定第一个值和最后一个值

  • 当<ColumnName>是文本格式时:

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

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

    时间顺序对第一参数的结果排序,FIRSTNONBLANK 返回升序排序的第一个值, LASTNONBLANK 返回最后一个值


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



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


7125211936391.png

示例表:Table


以上图中 Table 的数据为例,如果想要获得销售额不为空的第一个产品经理,有两种写法:
  1. F1 = FIRSTNONBLANK('Table'[地区经理],CALCULATE(SUM('Table'[销售额])))
  2. F2 = FIRSTNONBLANK('Table'[地区经理],SUM('Table'[销售额]))
复制代码

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


F2 的结果是「白德伟」,原因在于 F2 公式中的SUM('Table'[销售额])忽略行上下文,每行计值的结果相同,使得 FIRSTNONBLANK 在整个经理列表中计算最小值,得到了错误的结果。
在这个示例中,如果你想要返回楚杰对应的销售额,最简单的写法是使用 FIRSTNONBLANKVALUE
迭代函数的上下文转换

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

它返回在当前筛选上下文中,库存表数量列不为空的最近日期,你也可以用另一个等价公式:
  1. LASTNONBLANK ( Dates[Date], COUNTROWS ( RELATEDTABLE ( Inventory ) ) )
复制代码

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

可用作 CALCULATE 筛选器的表函数



FIRSTNONBLANK 和 LASTNONBLANK 返回标量值,但同时也可以作为 CALCULATE 函数的筛选器参数,因为本质上它们返回的是单行表。比如:
  1. Units LastNonBlank :=
  2.     CALCULATE (
  3.         SUM ( Inventory[UnitsBalance] ),
  4.         LASTNONBLANK (
  5.             'Date'[Date],
  6.             CALCULATE ( SUM ( Inventory[UnitsBalance] ) )
  7.         )
  8.     )
复制代码
LASTNONBLANK 与 LASTDATE 的区别

FIRSTNONBLANK/LASTNONBLANK 函数接受任何数据类型作为其第一参数,而 FIRSTDATE/LASTDATE 函数则需要列必须使用日期类型。如果日期值所在的列使用了另一种数据类型,你希望获得它在筛选上下文中的第一个或最后一个值时,需要使用 FIRSTNONBLANK/LASTNONBLANK 而不是 FIRSTDATE/LASTDATE,将任何非空表达式作为第二个参数传递。当然,你也可以考虑在这种情况下使用 TOPN 函数。
  1. TopDate :=
  2. TOPN (
  3.     1,
  4.     VALUES ( Date[DateKey] ),
  5.     [Internet Total Sales]
  6. )
复制代码

如果两个或两个以上的日期具有相同的最高销售额,则 TopDate 度量值将报错,因为 TOPN 返回了一个包含一列和两行或更多行的表,不能被转换为标量值。你可以对公式做如下改动:
  1. TopDate :=
  2. LASTNONBLANK (
  3.     TOPN (
  4.         1,
  5.         VALUES ( Date[DateKey] ),
  6.         [Internet Total Sales]
  7.     ),
  8.     1
  9. )
复制代码
理解 LASTNONBLANK 的第二参数
在 TopDate 公式的第二种写法中,LASTNONBLANK 使用了一个常数 1 作为第二参数,这种用法看似奇怪,如果我要做的就是查找列中的最后一个非空值,为什么需要这个第二个参数?简单的说,上面的示例中我们可以无视它(只因为它是必选参数才做了保留)。但是拥有第二参数让这个函数更加强大和灵活,因为它允许你自由定义DAX 表达式来实现你需要的计算逻辑。在一些简单情况下,当你只对第一列的最大值或最小值感兴趣的时候,有一个变通方法,只需使用值 1 作为第二个参数,就像这样:
  1. LASTNONBLANK(Table[Column], 1)
复制代码

第二参数区分 0 和 BLANK,0 也是非空值,和 1 的效果相同。当第二参数使用 BLANK()时,函数永远返回空值
  1. LASTNONBLANK(<AnyColumn>, BLANK()) = 空白
  2. FIRSTNONBLANK(<AnyColumn>, BLANK()) = 空白
复制代码


排序规则

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



当列为数值类型或日期类型时,函数从非空结果中返回第一参数的最小或最大值,下图左右两种写法等价:
  1. MIN ( <column> ) = FIRSTNONBLANK ( <column>, 1 )
  2. MAX ( <column> ) = LASTNONBLANK ( <column>, 1 )
复制代码

而当列为文本类型时,只能使用右侧的写法,函数从非空结果中按照第一参数的文本的首字母顺序返回结果,FIRSTNONBLANK 返回升序排序的第一个结果,LASTNONBLANK 返回降序排序的第一个结果。
第一参数<ColumnName>必须是单列。在某些情况下,当一个包含多列的表作为 ColumnName 参数时,函数不会报错,但这是错误用法
7125211936392.zip (157.35 KB, 下载次数: 0)
回复

使用道具 举报

fanzhenbo | 2021-4-24 12:48:42 | 显示全部楼层
鼎力支持!!
回复

使用道具 举报

GlitterMai | 2021-7-4 11:01:35 来自手机 | 显示全部楼层
纯粹路过,没任何兴趣,仅仅是看在老用户份上回复一下
回复

使用道具 举报

jerryho | 2021-7-15 20:05:43 来自手机 | 显示全部楼层
这个视频很不错,推荐一下
回复

使用道具 举报

风的方向 | 2021-8-28 10:45:32 | 显示全部楼层
介是神马?!!
回复

使用道具 举报

20082008 | 2021-9-8 21:33:33 来自手机 | 显示全部楼层
努力学习中
回复

使用道具 举报

平凡人 | 2021-9-16 22:31:43 | 显示全部楼层
努力蜕变中
回复

使用道具 举报

sibada | 2021-10-3 10:33:02 来自手机 | 显示全部楼层
支持,楼下的跟上哈~
回复

使用道具 举报

飞旋的青花 | 2021-10-19 14:04:21 来自手机 | 显示全部楼层
支持楼主,用户楼主,楼主英明呀!!!
回复

使用道具 举报

lizhongjie | 2021-11-7 13:53:32 | 显示全部楼层
楼主呀,,,您太有才了。。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则