【问题标题】:Counting latest instance of multiple only based on filter context仅基于过滤器上下文计算多个最新实例
【发布时间】:2018-07-12 21:53:52
【问题描述】:

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

此表从 SQL 数据库中提取到 Excel 2016 工作表中,我正在使用 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 中创建一个数据透视表(或使用 CUBE 函数等)来获得这样的输出表:

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 的答案的 cmets。

【问题讨论】:

    标签: ssas powerbi dax powerpivot excel-2016


    【解决方案1】:

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


    让我们在event_list 表中添加两列。一个在该日期计算车辆 "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 放在矩阵可视行部分,并将@​​987654333@ 和OutOfService 列添加到值部分(对聚合选项使用Maximum 或Minimum,而不是Sum)。


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

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

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

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

    【讨论】:

    • 谢谢!它看起来是一个更好的解决方案。我的特定数据集仍然存在一些性能问题,但这似乎是一个解决方案,因此我将其标记为这样。
    • 是的,在一个大集合上这将是资源密集型的,因为每一行都必须检查所有日期较早的行,但由于数据的记录方式,这是必要的。在将数据拉入 Power BI 之前对其进行重组可能是更好的解决方案。
    【解决方案2】:

    这是相当困难的。我没有一个很好的答案,但这里有一些可行的方法。

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

    = 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])
    

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

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

    结果应该是这样的:

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

    应该是这样的:

    【讨论】:

    • 输出看起来完全正确!我一直只使用 Excel 和 PowerPivot 来完成这项任务。看起来我可能会遇到该工具的限制。你的图片来自 PowerBI?我看看能不能让它跑起来。之前真的没用过。谢谢! (我试图支持你的答案,但我还没有足够的声誉!)
    • Power Pivot 也应该能够做到这一点。我只是更习惯于在 Power BI 中工作(它不那么笨重)而且我忘记了你没有那个标签。两者的 DAX 几乎相同。
    • 我似乎无法按照您在 PowerPivot 中的初始说明创建计算表。如果选项在那里,我还没有找到它。但是,我设法获得了 PowerBI 的副本,并一直在将数据移到那里并努力实施您的建议。
    • 我正在尝试实现这一点,但是我遇到了资源问题。实际的 event_list 表中有大约 250,000 多行,每个 ID 最多有 13 个序列。这导致交叉表大约有十亿行,并且 PowerBI 开始在序列计算列上引发内存错误。虽然这似乎是一个解决方案,但您对资源密集度较低的东西有什么建议吗?我们正在通过 Microsoft SQL Server 上的 SQL 查询拉表,并且还可以访问 SSAS 服务,如果这有助于为我指明更好的方向。
    • 是的,交叉连接方法在大型数据集上会很糟糕。我会尝试找到一种更有效的方法,但我可能没有时间,因为这不是一个容易的问题。我知道更清洁的解决方案是可能的,但我还没有完全确定。
    猜你喜欢
    • 2020-01-18
    • 1970-01-01
    • 1970-01-01
    • 2021-01-12
    • 2021-09-24
    • 2011-09-06
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多