[知识体系] 理解FIRSTDATE 和 LASTDATE

  [复制链接]
查看105014 | 回复117 | 2021-2-21 18:54:28 | 显示全部楼层 |阅读模式
在介绍LASTDATELASTNONBLANK。与它们相对应的还有两个函数用来获取第一个日期,而不是区间内的最后一个日期:FIRSTDATEFIRSTNONBLANK。本文描述 FIRSTDATELASTDATE 的行为,下一篇文章解释 FIRSTNONBLANKLASTNONBLANK

FIRSTDATE
  1. FIRSTDATE ( <Dates> )
复制代码


FIRSTDATELASTDATE 只操作日期列,它们分别返回活动筛选上下文中的第一个和最后一个日期,忽略其他相关表中存在的数据。其中<Dates>参数是单列日期类型的表,等价于:

  1. CALCULATETABLE ( DISTINCT ( <Dates> ) )
复制代码


FIRSTDATE 返回参数列在当前筛选上下文中的最小值,而 LASTDATE 返回的是最大值(注意,日期在内部表示为浮点数)。

用作 CALCULATE 筛选器的表函数

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

LASTDATE 与 MAX 的区别

FIRSTDATE/LASTDATE 和 MIN/MAX 函数的语义区别在于前者返回一个表并执行上下文转换,而后者返回一个标量值不执行任何上下文转换。这样做的原因是,当你将这些表达式放入 CALCULATE 函数的筛选器参数中时,可以简化 DAX 语法。


例如,观察下面这个表达式:

  1. CALCULATE (
  2.     SUM ( Inventory[Quantity] ),
  3.     LASTDATE ( 'Date'[Date] )
  4. )
复制代码


你可以用 MAX 代替 LASTDATE 将表达式改写成下面这种等效写法,但这会导致代码量增加:

  1. CALCULATE (
  2.     SUM ( Inventory[Quantity] ),
  3.     FILTER (
  4.         ALL ( 'Date'[Date] ),
  5.         'Date'[Date]
  6.             = MAX ( 'Date'[Date] )
  7.     )
  8. )
复制代码


实际上,LASTDATE 函数还会执行上下文转换。因此使用原生 DAX 重写的准确表达式如下:

  1. CALCULATE (
  2.     SUM ( Inventory[Quantity] ),
  3.     VAR LastDateInSelection =
  4.         MAXX ( CALCULATETABLE ( DISTINCT ( 'Date'[Date] ) ), 'Date'[Date] )
  5.     RETURN
  6.         FILTER ( ALL ( 'Date'[Date] ), 'Date'[Date] = LastDateInSelection )
  7. )
复制代码


行上下文中执行 FIRSTDATE/LASTDATE 时,需要考虑行上下文转换。最佳做法是

  • 当定义筛选器参数表达式时(结果是表) ,使用 FIRSTDATE / LASTDATE
  • 在行上下文中定义逻辑表达式时(通常结果是一个标量值) ,使用 MIN/MAX 函数


因为 LASTDATE 执行了上下文转换,隐藏了外部筛选上下文

行上下文转换时的不同行为



当用作 CALCULATE/CALCULATETABLE 函数的筛选器参数时,我们更倾向于使用 FIRSTDATE/LASTDATE 而不是 MIN/MAX,因为前者的语法更简单(我们已经看到过几个这种用法的示例)。但是,当 FIRSTDATE/LASTDATE 隐含的上下文转换改变计值行为时,为了避免这种情况,你应该使用 MIN/MAX, 比如 FILTER 函数中的条件计算属于这种情况。下面的表达式筛选出了用于计算移动总计的日期

  1. FILTER (
  2.     ALL ( 'Date'[Date] ),
  3.     'Date'[Date]
  4.         <= MAX ( 'Date'[Date] )
  5. )
复制代码


使用 MAX 是正确的做法。事实上,如果你用 LASTDATE 而不是 MAX,你不会得到任何错误提示,但结果总是全部日期,忽略外部筛选上下文。因此,下面的表达总是错的:

  1. FILTER (
  2.     ALL ( 'Date'[Date] ),
  3.     'Date'[Date]
  4.         <= LASTDATE ( 'Date'[Date] )
  5. )
复制代码


我们使用以下两个版本的度量值计算移动总计筛选器返回的天数即可看出问题:

  1. [RT Days MAX] :=
  2. COUNTROWS (
  3.     FILTER (
  4.         ALL ( 'Date'[Date] ),
  5.         'Date'[Date]
  6.             <= MAX ( 'Date'[Date] )
  7.     )
  8. )

  9. [RT Days LASTDATE] :=
  10. COUNTROWS (
  11.     FILTER (
  12.         ALL ( 'Date'[Date] ),
  13.         'Date'[Date]
  14.             <= LASTDATE ( 'Date'[Date] )
  15.     )
  16. )
复制代码


图 7-43 显示筛选出的移动总计天数对于 RT Days MAX 度量值是正确的,但是对于 RT Days LASTDATE 是错误的。原因是 LASTDATE 为每个日期执行上下文转换后总是返回当前行的值,最终导致 FILTER 返回所有日期。


7087211936381.jpeg

图 7-43 RT Days LASTDATE 总是统计日期表的所有行

LASTDATE.xlsx (4.45 MB, 下载次数: 0)
回复

使用道具 举报

秋天的农药 | 2021-4-24 14:16:51 | 显示全部楼层
支持一下,天天来这学习
回复

使用道具 举报

dgfishman | 2021-5-1 20:52:19 | 显示全部楼层
广告位,,坐下看看
回复

使用道具 举报

阿丫 | 2021-6-23 11:48:06 | 显示全部楼层
珍爱生命,果断回帖。
回复

使用道具 举报

zhenblisa | 2021-7-30 08:54:20 | 显示全部楼层
路过 帮顶 嘿嘿
回复

使用道具 举报

beer | 2021-8-30 12:14:12 | 显示全部楼层
元芳你怎么看?
回复

使用道具 举报

qinyi | 2021-10-30 06:07:53 | 显示全部楼层
支持支持再支持
回复

使用道具 举报

zhouli31894 | 2021-11-5 15:22:03 来自手机 | 显示全部楼层
好,很好,非常好!
回复

使用道具 举报

nikos | 2021-11-8 17:27:44 | 显示全部楼层
very good。。。。。
回复

使用道具 举报

野仔 | 2021-11-23 11:26:26 | 显示全部楼层
看起来好像不错的样子
回复

使用道具 举报

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

本版积分规则