其他时间智能计算

已完成

存在涉及返回单个日期的其他 DAX 时间智能函数。 你将通过在两个不同的方案中应用这些函数来了解它们。

FIRSTDATELASTDATE DAX 函数返回当前筛选器上下文中指定日期列的第一个日期和最后一个日期。

计算新情况

时间智能函数的另一个用途是对新情况进行计数。 下面的示例演示如何计算一段时间内的新客户数。 新客户在其第一次购买的时间段内进行计数。

第一项任务是向 Sales 表添加以下度量值,用于统计迄今 (LTD) 不同客户数。 “迄今”是指筛选器上下文中从开始时间直到最后一个日期。 使用千位分隔符将度量值的格式设置为整数。

Customers LTD =
VAR CustomersLTD =
    CALCULATE(
        DISTINCTCOUNT(Sales[CustomerKey]),
        DATESBETWEEN(
            'Date'[Date],
            BLANK(),
            MAX('Date'[Date])
        ),
        'Sales Order'[Channel] = "Internet"
    )
RETURN
    CustomersLTD

将“客户 LTD”度量值添加到矩阵视觉对象。 请注意,它将生成不同客户 LTD 的结果,直到每月结束。

图像显示了一个矩阵视觉对象,其中包含“年份”和“月份”行组以及“收入”、“收入 YTD”、“收入 YoY 百分比”和“客户 LTD”。

DATESBETWEEN 函数返回一个包含日期列的表,该日期列以给定的开始日期开始,并一直持续到给定的结束日期。 当开始日期为空时,它将使用日期列中的第一个日期。 (相反,当结束日期为空时,它将使用日期列中的最后一个日期。)在这种情况下,结束日期由 MAX 函数确定,它返回筛选器上下文中的最后一个日期。 因此,如果 2017 年 8 月这一月份在筛选器上下文中,则 MAX 函数将返回 2017 年 8 月 31 日,而 DATESBETWEEN 函数将返回一直到 2017 年 8 月 31 日的所有日期。

接下来,你将修改该度量值,方法是将其重命名为“新客户”,并添加第二个变量来存储筛选器上下文中时间段之前的不同客户数。 RETURN 子句现从 LTD 客户中减去该值以生成结果,这是该时间段内新客户的数量。

New Customers =
VAR CustomersLTD =
    CALCULATE(
        DISTINCTCOUNT(Sales[CustomerKey]),
        DATESBETWEEN(
            'Date'[Date],
            BLANK(),
            MAX('Date'[Date])
        ),
    'Sales Order'[Channel] = "Internet"
    )
VAR CustomersPrior =
    CALCULATE(
        DISTINCTCOUNT(Sales[CustomerKey]),
        DATESBETWEEN(
            'Date'[Date],
            BLANK(),
            MIN('Date'[Date]) - 1
        ),
        'Sales Order'[Channel] = "Internet"
    )
RETURN
    CustomersLTD - CustomersPrior

图像显示了一个矩阵视觉对象,其中包含“年份”和“月份”行组以及“收入”、“收入 YTD”、“收入 YoY 百分比”和“新客户”。将突出显示新客户值。

对于 CustomersPrior 变量,请注意,DATESBETWEEN 函数包括筛选器上下文中的第一个日期减 1 之前的日期。 由于 Microsoft Power BI 在内部将日期存储为数字,因此可以加减数字来转换日期。

快照计算

偶尔,事实数据在时间上存储为快照。 常见示例包括库存水平或帐户余货。 值快照定期加载到表中。

汇总快照值时(如库存水平),可以汇总除日期之外的任何维度中的值。 在产品类别之间添加库存水平计数将生成有意义的摘要,但在日期之间添加库存水平计数则不会。 将昨天的库存水平添加到今天的库存水平并非有效操作(除非你想要计算该结果的平均值)。

在对快照表进行汇总时,度量值公式可以依赖于 DAX 时间智能函数来强制实施单个日期筛选器。

在下面的示例中,你将浏览一个 Adventure Works 公司的方案。 切换到模型视图,然后选择“库存”模型关系图。

图像显示包含三个表的模型关系图:“产品”、“日期”和“库存”。每个“产品”和“日期”表都具有与“库存”表之间的一对多关系。

请注意,该关系图显示三个表:Product、Date 和 Inventory。 Inventory 表存储每个日期和产品的单位余货快照。 重要的是,该表没有任何遗漏的日期,也不包含相同日期的任何产品的重复条目。 此外,最后一条快照记录存储为 2020 年 6 月 15 日。

现在,切换到报表视图,选择报表第 2 页。 将 Inventory 表的“UnitsBalance”列添加到矩阵视觉对象。 其默认摘要设置为值的总和。

图像显示标题为“FY2020 Mountain-200 自行车存货”的矩阵视觉对象。它按照“产品”行和“月份”列进行分组。每个产品和月份显示较高值。

此视觉对象配置是一个示例,演示了如何不对快照值进行汇总。 将每日快照余货相加不会产生有意义的结果。 因此,请从矩阵视觉对象中删除“UnitsBalance”字段。

现在将向 Inventory 表添加用于将单个日期“UnitsBalance”值相加的度量值。 该日期将为每个时间段的最后日期。 它通过 LASTDATE 函数来实现。 使用千位分隔符将度量值的格式设置为整数。

Stock on Hand =
CALCULATE(
    SUM(Inventory[UnitsBalance]),
    LASTDATE('Date'[Date])
)

注意

请注意,度量值公式使用 SUM 函数。 必须使用聚合函数(度量值不允许直接引用列),但如果每个日期的每个产品只有一行,则 SUM 函数将只对单个行进行运算。

将“存货”度量值添加到矩阵视觉对象。 此时,每个产品的值将基于每个月最后记录的余货台数。

图像显示标题为“FY2020 Mountain-200 自行车存货”的矩阵视觉对象。它按照“产品”行和“月份”列进行分组。每个产品和月份显示较低值。2020 年 6 月,“总计”为空。

度量值为 2020 年 6 月返回空值,因为 6 月的最后一个日期不存在记录。 可以从数据中看到还没有出现任何记录。

按筛选器上下文中的最后一个日期进行筛选存在固有问题:记录的日期可能不存在,因为可能尚未发生,也可能是因为周末未记录库存余货。

下一步是调整度量值公式,以确定包含非空结果的最后日期,然后按该日期进行筛选。 可以使用 LASTNONBLANK DAX 函数来实现此任务。

使用以下度量值定义来修改现有“存货”度量值。

Stock on Hand =
CALCULATE(
    SUM(Inventory[UnitsBalance]),
    LASTNONBLANK(
        'Date'[Date],
        CALCULATE(SUM(Inventory[UnitsBalance]))
    )
)

在矩阵视觉对象中,注意 2020 年 6 月的值和总计(表示全年)。

图像显示矩阵视觉对象现具有 2020 年 6 月的值和总计。

LASTNONBLANK 函数是一个迭代器函数。 它将返回生成非空结果的最后日期。 它通过以下方式实现此结果:按降序时间顺序循环访问筛选器上下文中的所有日期。 (相反,FIRSTNONBLANK 将按顺序时间升序循环访问。)对于每个日期,它将计算传入的表达式。 如果遇到非空结果,该函数将返回日期。 然后,使用该日期筛选 CALCULATE 函数。

注意

LASTNONBLANK 函数在行上下文中计算其表达式。 必须使用 CALCULATE 函数将行上下文转换为筛选器上下文,以正确计算表达式的值。

现在应隐藏“库存”表的“UnitsBalance”列。 它将阻止报表作者对快照余货台数进行不当汇总。