计算累计有两类常用的时间智能函数,以 DATESYTD 为代表的返回日期值的表函数和以 TOTALYTD 为代表的返回标量值的函数。
计算累计有两类常用的时间智能函数,以 DATESYTD 为代表的返回日期值的表函数和以 TOTALYTD 为代表的返回标量值的函数。
DATESYTD
- DATESYTD ( <Dates>, [<YearEndDate>] )
复制代码
在当前上下文环境中,返回一张单列的日期表,其中包含当前年份到目前为止的所有日期。
参数 | 属性 | 描述 | Dates | | 日期格式的列或返回单列的表达式,通常使用日期表的日期列 | YearEndDate | 可选 | 年截止日,日期字符串,忽略年 |
- ------------- 从 1 月 1 日开始计算的年累计销售额(默认) ---------------
- Example1 = CALCULATE(SUM(Sales[SalesAmount]), DATESYTD(DateTime[DateKey]))
- ------------- 从 7 月 1 日开始计算的年累计销售额 ---------------
- Example2 = CALCULATE(SUM(Sales[SalesAmount]), DATESYTD(DateTime[DateKey],"6/30"))
复制代码
从语义上,DATESYTD 等价于下面的表达式:
- DATESBETWEEN (
- <Dates>,
- STARTOFYEAR ( LASTDATE ( <Dates> ), [<YearEndDate>] ),
- LASTDATE ( <Dates> )
- )
复制代码
与 DATESYTD 类似的时间智能函数还有
- 季度累计:DATESQTD
- 月累计:DATESMTD
TOTALYTD
- TOTALYTD ( <Expression>, <Dates>, [ <Filter>], [ <YearEndDate>] )
复制代码
计算当前计值上下文中表达式的年初至今值,TOTALYTD 返回标量结果,是 CALCULATE+DATESYTD 的简化形式,语义更直观。
参数 | 属性 | 描述 | Expression | | 需要计值的表达式 | Dates | | 日期格式的列或由单个日期列构成的表,通常使用日期表的日期列 | Filter | 可选 | 布尔表达式或定义了筛选器的表表达式 | YearEndDate | 可选 | 年截止日 |
- ------------- 从 1 月 1 日开始计算的年累计销售额(默认) ---------------
- Example1 = TOTALYTD(SUM(Sales[SalesAmount]), DateTime[DateKey])
- ------------- 从 7 月 1 日开始计算的年累计销售额 ---------------
- Example2 = TOTALYTD(SUM(Sales[SalesAmount]), DateTime[DateKey],"6/30")
- ------------- 从 7 月 1 日开始计算的年累计销售额,忽略来自日期表的其他筛选器 ---------------
- Example3 = TOTALYTD(SUM(Sales[SalesAmount]), DateTime[DateKey],ALL(DateTime),"6/30")
复制代码
从语义上,TOTALYTD 等价于下面的表达式:
- CALCULATE (
- <Expression>,
- DATESYTD ( <Dates>, [<YearEndDate>] ),
- [<Filter>]
- )
复制代码
与 TOTALYTD 类似的时间智能函数还有
- 季度累计:TOTALQTD
- 月累计:TOTALMTD
使用基础函数重写 DATESYTD
你已经学习了计算月累计、季度累计和年累计的 DAX 函数,如果使用 TOTALYTD、TOTALQTD 或 TOTALMTD 这些标量函数,它们的实现方式是通过调用 DATESYTD、DATESQTD 和 DATESMTD 来确定日期筛选器,而每个筛选器函数都可以通过在 DAX 中编写 FILTER 语句实现类似的结果。这种编写方式虽然并不常用,但对于理解时间智能函数的本质非常重要。而且,当你使用 DirectQuery 模式时,时间智能函数是不可用的,你必须使用基础函数来实现时间智能的计算逻辑。
例如,考虑下面这个 DATESYTD 函数
- DATESYTD ( 'Date'[Date] )
复制代码
它相当于在日期列上使用由 CALCULATETABLE 调用的 FILTER 筛选器,如以下代码所示:
- CALCULATETABLE (
- FILTER (
- ALL ( 'Date'[Date] ),
- AND (
- 'Date'[Date] <= MAX ( 'Date'[Date] ),
- YEAR ( 'Date'[Date] ) = YEAR ( MAX ( 'Date'[Date] ) )
- )
- )
- )
复制代码
同样的,DATESMTD 函数
- DATESMTD ( 'Date'[Date] )
复制代码
对应下面这段代码:
- CALCULATETABLE (
- FILTER (
- ALL ( 'Date'[Date] ),
- AND (
- 'Date'[Date] <= MAX ( 'Date'[Date] ),
- AND (
- YEAR ( 'Date'[Date] ) = YEAR ( MAX ( 'Date'[Date] ) ),
- MONTH ( 'Date'[Date] ) = MONTH ( MAX ( 'Date'[Date] ) )
- )
- )
- )
- )
复制代码
DATESQTD 函数与 DATESMTD 类似,只需要将上面高亮部分的 MONTH 函数替换为 QUARTER。
所有这些替代实现方式都有一个共同的特点:它们从当前上下文的最新日期中提取有关年份、月份和季度的信息。使用 CALCULATETABLE 调用 FILTER 的原因是执行上下文转换。然而,如果在计算列中使用这种技术可能会很慢,这些函数在内部实现时得到了优化,你可以使用两种不同的技术来获得更好的性能。
如果不存在行上下文,你可以直接移除 CALCULATETABLE。通常,在 CALCULATE 中调用的筛选器参数就属于这种情况,比如 DATESYTD,所以 DATESYTD 可以写成:
- FILTER (
- ALL ( 'Date'[Date] ),
- AND (
- 'Date'[Date] <= MAX ( 'Date'[Date] ),
- YEAR ( 'Date'[Date] ) = YEAR ( MAX ( 'Date'[Date] ) )
- )
- )
复制代码
如果你想要使用的日期存在行上下文,例如在计算列中,那么你可以使用 EARLIER 代替 MAX:
- FILTER (
- ALL ( 'Date'[Date] ),
- AND (
- 'Date'[Date] <= EARLIER ( 'Date'[Date] ),
- YEAR ( 'Date'[Date] ) = YEAR ( EARLIER ( 'Date'[Date] ) )
- )
- )
复制代码
DATESYTD 的第二个参数允许自定义年的截止日期。例如,对于从 7 月 1 日开始的财年,你在第二个参数中指定了 6 月 30 日(根据本地语言设置,使用以下版本之一):
- DATESYTD ( 'Date'[Date], "06-30" )
- DATESYTD ( 'Date'[Date], "30-06" )
复制代码
不考虑本地语言设置,我们假设你指定了天(<day>)和月份(<month>),则这个版本的 DATESYTD 对应的 FILTER 版本写法如下:
- VAR LastInSelection = MAX ( 'Date'[Date] )
- VAR SelectionEndOfYear =
- DATE ( YEAR ( LastInSelection ), <month>, <day> )
- VAR DifferentYear = ( SelectionEndOfYear >= LastInSelection )
- VAR LastDayPreviousYear =
- DATE ( YEAR ( LastInSelection ) - DifferentYear, <month>, <day> )
- RETURN
- FILTER (
- ALL ( 'Date'[Date] ),
- 'Date'[Date] > LastDayPreviousYear
- && 'Date'[Date] <= LastInSelection
- )
复制代码
|