仅根据过滤器上下文计算多个最新实例

Counting latest instance of multiple only based on filter context

我有大量 table 车辆清单中发生的事件,这些事件会影响它们是在使用还是停止使用。我想创建一个度量,能够根据 table 中的事件在任何时间点计算各种库存中的车辆数量。

此 table 从 SQL 数据库提取到 Excel 2016 sheet,我正在使用 PowerPivot 尝试得出 DAX 度量.

这是一些示例数据event_list:

vehicle_id    event_date    event         event_sequence    inventory
100           2018-01-01    purchase      1                 in-service
101           2018-01-01    purchase      1                 in-service
102           2018-02-04    purchase      1                 in-service
100           2018-02-07    maintenance   2                 out-of-service
101           2018-02-14    damage        2                 out-of-service
101           2018-02-18    repaired      3                 in-service
100           2018-03-15    repaired      3                 in-service
102           2018-05-01    damage        2                 out-of-service
103           2018-06-03    purchase      1                 in-service

我希望能够在 Excel 中创建一个枢轴 table(或使用 CUBE 函数等)以获得这样的输出 table:

date          in-service     out-of-service
2018-02-04    3              0
2018-02-14    1              2
2018-03-15    3              0
2018-06-03    3              1

本质上,我希望能够根据任何时间日期计算库存。该示例只有几个日期,但希望能提供足够的图片。

到目前为止,我基本上已经想到了这个,但它计算的车辆数量超过了预期 - 我不知道如何只使用最新的 event_sequence 或 event_date 并使用它清点存货。

cumulative_vehicles_at_date:=CALCULATE(
    COUNTA([vehicle_id]),
    IF(IF(HASONEVALUE (event_list[event_date]), VALUES (event_list[event_date]))>=event_list[event_date],event_list[event_date])
)

我尝试使用 MAX() 和 EARLIER() 函数,但它们似乎不起作用。

编辑:添加了 PowerBI 标签,因为我现在也在使用该软件来尝试解决这个问题。查看对 Alexis Olson 回答的评论。

这很难。我没有很好的答案,但这里有一些有用的东西。

您将创建一个新的计算 table,您将在其中计算每个日期每辆车的状态。从每辆车和每个日期的基本交叉连接开始:

= CROSSJOIN(VALUES(event_list[vehicle_id]), VALUES(event_list[event_date]))

然后添加计算列以查找该日期每辆车的最大序列号。

Sequence = MAXX(
               FILTER(event_list,
                   event_list[event_date] <= Cross[event_date] &&
                   event_list[vehicle_id] = Cross[vehicle_id]),
               event_list[event_sequence])

现在您可以使用另一个计算列查找每个 vehicle/sequence 对的库存值:

Inventory = LOOKUPVALUE(
                event_list[inventory],
                event_list[vehicle_id], Cross[vehicle_id],
                event_list[event_sequence], Cross[Sequence]) 

结果应如下所示:

一旦你有了这个,你就可以使用这个计算的 table 创建一个矩阵。将 event_date 放在行上,将 Inventory 放在列上。在视觉级别筛选器中筛选出空白库存值,并将 vehicle_id 放入值字段中,使用计数或非重复计数作为聚合方法(而不是默认总和)。

它应该是这样的:

我想我找到了比我之前给出的方法更简洁的方法。


让我们在 event_list table 上添加两列。一种计算该日期的车辆 "in-service",另一种计算该日期的车辆 "out-of-service"

InService = 
    VAR Summary = SUMMARIZE(
                      FILTER(event_list,
                          event_list[event_date] <= EARLIER(event_list[event_date])),
                      event_list[vehicle_id],
                      "MaxSeq", MAX(event_list[event_sequence]))

    VAR Filtered = FILTER(event_list,
                       event_list[event_sequence] =
                           MAXX(
                               FILTER(Summary,
                                   event_list[vehicle_id] = EARLIER(event_list[vehicle_id])),
                               [MaxSeq]))

    RETURN SUMX(Filtered, 1 * (event_list[inventory] = "in-service"))

您可以为 OutOfService 创建一个类似的计算列,或者您可以只取总数减去 InService 计数。

OutOfService =
    CALCULATE(
        DISTINCTCOUNT(event_list[vehicle_id]),
        FILTER(event_list,
            event_list[event_date] <= EARLIER(event_list[event_date])))
    - event_list[InService]

现在您所要做的就是将 event_date 放在矩阵可视行部分,并将 InServiceOutOfService 列添加到值部分(使用最大值或最小值作为聚合选项而不是 Sum)。


这是计算列背后的逻辑 InService:

我们首先创建一个 Summary table 来计算每辆车的最大 event_sequence 值。 (我们过滤 event_date 以仅考虑我们正在使用的当前日期之前的日期。)

现在我们知道每辆车的最后一个 event_sequence 值是什么,我们使用它来过滤整个 table 到仅与这些车辆和序列值对应的行。过滤器逐行遍历 table 并检查序列值是否与我们在 Summary table 中计算的值匹配。请注意,当我们将 Summary table 过滤为我们当前正在使用的车辆时,我们只会得到一行。我只是使用 MAXX 来提取 [MaxSeq] 值。 (这有点像使用 LOOKUPVALUE,但你不能在变量上使用它。)

现在我们已经过滤了 table 每辆车的最新事件,我们需要做的就是计算其中有多少 "in-service"。我在这里使用了 SUMX,其中 1*(True/False) 将布尔值强制为 return 10.