FIRSTDATE 和 LASTDATE 函数可以用来获取第一个日期和最后一个日期,并以表的形式返回,在用作CALCULATE函数的内部筛选器参数时可以有效简化代码的书写。
语法和作用
语法:
FIRSTDATE ( <Dates> )
LASTDATE ( <Dates> )
作用:返回参数所指定的日期字段在当前计值环境中的可见数据的第一个日期或最后一个日期,并以表的形式返回,结果表是一个单行单列的表。
注意:
1、FIRSTDATE 和 LASTDATE 函数的参数必须是日期类型的字段或单列表。
2、日期参数可以接受三种类型的输入,分别为:对日期列的引用、具有单个日期列的表、以及定义单个日期列表的布尔表达式。
3、这两个函数的参数如果是对日期列的引用,那么会触发行上下文转换。
辅助理解的例子
1、FIRSTDATE函数返回的是参数所指定的日期字段在当前计值环境中的可见数据的第一个日期,如下图所示:
2、LASTDATE函数返回的是参数所指定的日期字段在当前计值环境中的可见数据的最后一个日期,如下图所示:
3、如果用代码来表示的话,那么FIRSTDATE函数与LASTDATE函数的等价写法如下:
- FIRSTDATE函数的等价写法:
FIRSTDATE('Table'[Date])
等价于:
VAR DateParamTable = CALCULATETABLE(DISTINCT('Table'[Date])) // 参数所指定的日期单列表
VAR MinDate = MINX(DateParamTable,'Table'[Date]) // 找出第一个日期
RETURN
TREATAS({MinDate},'Table'[Date]) // 最后返回的是具有数据沿袭的单行单列的表
- LASTDATE函数的等价写法:
LASTDATE('Table'[Date])
等价于:
VAR DateParamTable = CALCULATETABLE(DISTINCT('Table'[Date])) // 参数所指定的日期单列表
VAR MaxDate = MAXX(DateParamTable,'Table'[Date]) // 找出最后一个日期
RETURN
TREATAS({MaxDate},'Table'[Date]) // 最后返回的是具有数据沿袭的单行单列的表
4、这两个函数的第一参数可以接受三种输入,其中一种就是直接引用日期列,而不需要借助任何表函数,因为它等价于:
CALCULATETABLE ( DISTINCT ( Table[ColumnName] ) )
因此,如果第一参数是直接引用日期列,那么还会触发行上下文转换,如下图所示:
由于行上下文转换,使得日期字段的可见数据只有当前行的单个日期,因此无论是返回第一个还是最后一个,都是当前行本身的日期。
5、除了直接引用日期列,这两个函数的第一参数还可以接受具有单个日期列的表、以及定义单个日期列表的布尔表达式,如下图所示:
使用这两种写法时可能会出现红色波浪线的警告,这可能是智能感知功能出了Bug,语法是没问题的,忽略即可。另外,定义单列表的布尔表达式其实也是一个语法糖,它跟CALCULATE函数的布尔筛选是一样的,完整写法如下:
FIRSTDATE('Table'[Date]>dt"2025-1-2")
等价于:
FIRSTDATE(FILTER(ALL('Table'[Date]),'Table'[Date]>dt"2025-1-2"))
需要注意的是,当第一参数不是直接引用日期列时,是不会触发行上下文转换的,如下图所示:
由于没有发生行上下文转换,因此第一参数的VALUES函数返回了全部日期,所以每一行都返回了全部日期中的第一个。
6、由于 FIRSTDATE 和 LASTDATE 函数返回的是表,因此可以直接用作CALCULATE函数的内部筛选器,从而减少代码的书写,比如以下表达式:
CALCULATE (
SUM ( 'Table'[Sales] ),
LASTDATE ( 'Table'[Date] )
)
如果使用MAX函数来代替LASTDATE函数的话,那么代码量会有所增加,具体如下:
CALCULATE (
SUM ( 'Table'[Sales] ),
FILTER ( ALL ( 'Table'[Date] ), 'Table'[Date] = MAX ( 'Table'[Date] ) )
)
总结
FIRSTDATE 和 LASTDATE函数的行为类似于MIN/MAX函数,但由于返回的是表并且可以触发行上下文转换,所以在部分场景中能够简化代码书写量,建议掌握。