[知识体系] DATESYTD 和 TOTALYTD

  [复制链接]
查看300004 | 回复199 | 2021-2-21 18:54:47 | 显示全部楼层 |阅读模式
计算累计有两类常用的时间智能函数,以 DATESYTD 为代表的返回日期值的表函数和以 TOTALYTD 为代表的返回标量值的函数。
计算累计有两类常用的时间智能函数,以 DATESYTD 为代表的返回日期值的表函数和以 TOTALYTD 为代表的返回标量值的函数。

DATESYTD
  1. DATESYTD ( <Dates>, [<YearEndDate>] )
复制代码


在当前上下文环境中,返回一张单列的日期表,其中包含当前年份到目前为止的所有日期。

参数属性描述
Dates日期格式的列或返回单列的表达式,通常使用日期表的日期列
YearEndDate可选年截止日,日期字符串,忽略年

  1. ------------- 从 1 月 1 日开始计算的年累计销售额(默认) ---------------
  2. Example1 = CALCULATE(SUM(Sales[SalesAmount]), DATESYTD(DateTime[DateKey]))

  3. ------------- 从 7 月 1 日开始计算的年累计销售额 ---------------
  4. Example2 = CALCULATE(SUM(Sales[SalesAmount]), DATESYTD(DateTime[DateKey],"6/30"))
复制代码


从语义上,DATESYTD 等价于下面的表达式:

  1. DATESBETWEEN (
  2.     <Dates>,
  3.     STARTOFYEAR ( LASTDATE ( <Dates> ), [<YearEndDate>] ),
  4.     LASTDATE ( <Dates> )
  5. )
复制代码


DATESYTD 类似的时间智能函数还有

  • 季度累计:DATESQTD
  • 月累计:DATESMTD

TOTALYTD
  1. TOTALYTD ( <Expression>, <Dates>, [ <Filter>], [ <YearEndDate>] )
复制代码


计算当前计值上下文中表达式的年初至今值,TOTALYTD 返回标量结果,是 CALCULATE+DATESYTD 的简化形式,语义更直观。

参数属性描述
Expression需要计值的表达式
Dates日期格式的列或由单个日期列构成的表,通常使用日期表的日期列
Filter可选布尔表达式或定义了筛选器的表表达式
YearEndDate可选年截止日

  1. ------------- 从 1 月 1 日开始计算的年累计销售额(默认) ---------------
  2. Example1 = TOTALYTD(SUM(Sales[SalesAmount]), DateTime[DateKey])
  3. ------------- 从 7 月 1 日开始计算的年累计销售额 ---------------
  4. Example2 = TOTALYTD(SUM(Sales[SalesAmount]), DateTime[DateKey],"6/30")
  5. ------------- 从 7 月 1 日开始计算的年累计销售额,忽略来自日期表的其他筛选器 ---------------
  6. Example3 = TOTALYTD(SUM(Sales[SalesAmount]), DateTime[DateKey],ALL(DateTime),"6/30")
复制代码


从语义上,TOTALYTD 等价于下面的表达式:

  1. CALCULATE (
  2.     <Expression>,
  3.     DATESYTD ( <Dates>, [<YearEndDate>] ),
  4.     [<Filter>]
  5. )
复制代码


与 TOTALYTD 类似的时间智能函数还有

  • 季度累计:TOTALQTD
  • 月累计:TOTALMTD

使用基础函数重写 DATESYTD

你已经学习了计算月累计、季度累计和年累计的 DAX 函数,如果使用 TOTALYTD、TOTALQTDTOTALMTD 这些标量函数,它们的实现方式是通过调用 DATESYTD、DATESQTDDATESMTD 来确定日期筛选器,而每个筛选器函数都可以通过在 DAX 中编写 FILTER 语句实现类似的结果。
这种编写方式虽然并不常用,但对于理解时间智能函数的本质非常重要。而且,当你使用 DirectQuery 模式时,时间智能函数是不可用的,你必须使用基础函数来实现时间智能的计算逻辑。


例如,考虑下面这个 DATESYTD 函数

  1. DATESYTD ( 'Date'[Date] )
复制代码


它相当于在日期列上使用由 CALCULATETABLE 调用的 FILTER 筛选器,如以下代码所示:

  1. CALCULATETABLE (
  2.     FILTER (
  3.         ALL ( 'Date'[Date] ),
  4.         AND (
  5.             'Date'[Date] <= MAX ( 'Date'[Date] ),
  6.             YEAR ( 'Date'[Date] ) = YEAR ( MAX ( 'Date'[Date] ) )
  7.         )
  8.     )
  9. )
复制代码


同样的,DATESMTD 函数

  1. DATESMTD ( 'Date'[Date] )
复制代码


对应下面这段代码:

  1. CALCULATETABLE (
  2.     FILTER (
  3.         ALL ( 'Date'[Date] ),
  4.         AND (
  5.             'Date'[Date] <= MAX ( 'Date'[Date] ),
  6.             AND (
  7.                 YEAR ( 'Date'[Date] ) = YEAR ( MAX ( 'Date'[Date] ) ),
  8.                 MONTH ( 'Date'[Date] ) = MONTH ( MAX ( 'Date'[Date] ) )
  9.             )
  10.         )
  11.     )
  12. )
复制代码


DATESQTD 函数与 DATESMTD 类似,只需要将上面高亮部分的 MONTH 函数替换为 QUARTER。


所有这些替代实现方式都有一个共同的特点:它们从当前上下文的最新日期中提取有关年份、月份和季度的信息。使用 CALCULATETABLE 调用 FILTER 的原因是执行上下文转换。然而,如果在计算列中使用这种技术可能会很慢,这些函数在内部实现时得到了优化,你可以使用两种不同的技术来获得更好的性能。


如果不存在行上下文,你可以直接移除 CALCULATETABLE。通常,在 CALCULATE 中调用的筛选器参数就属于这种情况,比如 DATESYTD,所以 DATESYTD 可以写成:

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


如果你想要使用的日期存在行上下文,例如在计算列中,那么你可以使用 EARLIER 代替 MAX

  1. FILTER (
  2.     ALL ( 'Date'[Date] ),
  3.     AND (
  4.         'Date'[Date] <= EARLIER ( 'Date'[Date] ),
  5.         YEAR ( 'Date'[Date] ) = YEAR ( EARLIER ( 'Date'[Date] ) )
  6.     )
  7. )
复制代码


DATESYTD 的第二个参数允许自定义年的截止日期。例如,对于从 7 月 1 日开始的财年,你在第二个参数中指定了 6 月 30 日(根据本地语言设置,使用以下版本之一):

  1. DATESYTD ( 'Date'[Date], "06-30" )
  2. DATESYTD ( 'Date'[Date], "30-06" )
复制代码


不考虑本地语言设置,我们假设你指定了天(<day>)和月份(<month>),则这个版本的 DATESYTD 对应的 FILTER 版本写法如下:

  1. VAR LastInSelection = MAX ( 'Date'[Date] )
  2. VAR SelectionEndOfYear =
  3.     DATE ( YEAR ( LastInSelection ), <month>, <day> )
  4. VAR DifferentYear = ( SelectionEndOfYear >= LastInSelection )
  5. VAR LastDayPreviousYear =
  6.     DATE ( YEAR ( LastInSelection ) - DifferentYear, <month>, <day> )
  7. RETURN
  8.     FILTER (
  9.         ALL ( 'Date'[Date] ),
  10.         'Date'[Date] > LastDayPreviousYear
  11.             && 'Date'[Date] <= LastInSelection
  12.     )
复制代码

回复

使用道具 举报

lw44 | 2021-4-24 14:32:19 | 显示全部楼层
介是神马?!!
回复

使用道具 举报

wayne | 2021-6-4 18:12:15 | 显示全部楼层
纯粹路过,没任何兴趣,仅仅是看在老用户份上回复一下
回复

使用道具 举报

dongsian | 2021-6-14 16:45:03 | 显示全部楼层
回个帖子支持一下!
回复

使用道具 举报

帅仔 | 2021-6-28 21:28:54 来自手机 | 显示全部楼层
好,很好,非常好!
回复

使用道具 举报

fivemeteor | 2021-7-6 21:46:47 | 显示全部楼层
支持楼主,用户楼主,楼主英明呀!!!
回复

使用道具 举报

shanghaiaaa | 2021-8-7 21:15:42 | 显示全部楼层
看起来不错
回复

使用道具 举报

sisisi | 2021-8-11 17:28:27 | 显示全部楼层
围观 围观 沙发在哪里!!!
回复

使用道具 举报

7月11日 | 2021-9-9 14:31:47 来自手机 | 显示全部楼层
这套视频很不错!!!!
回复

使用道具 举报

ysg168 | 2021-10-21 14:05:00 | 显示全部楼层
纯粹路过,没任何兴趣,仅仅是看在老用户份上回复一下
回复

使用道具 举报

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

本版积分规则