【问题标题】:DAX closest value match with no relationshipDAX 最接近的值匹配,没有关系
【发布时间】:2016-11-23 17:45:00
【问题描述】:

我正在尝试将报表从 Excel 迁移到 Power BI,我希望有人可以帮助我,因为我是 DAX 新手。

我有两张表,一张(我们称之为表 A)包含一列计划的事件开始日期/时间,而另一个包含相同事件的实际开始日期/时间。计划开始时间和实际开始时间之间通常只有几分钟的差异。

我需要将表 B 中最接近的实际开始日期/时间与表 A 中计划的开始日期/时间相匹配。

没有可用于在两个表之间创建关系的现有列。

如果我能找到最接近的实际开始时间并将其拉入表 A,那么我可以从中创建关系。

在 Excel 中,我会使用这样的数组公式来执行此操作:(这里我只是假设所有内容都在每个表的 A 列中)

{=Index(TableB!A:A,match(min(abs(TableB!A:A-TableA!A1)),abs(TableB!:A:A-TableA!A1),0),1)}

我在网上找到了以下 DAX 代码,但即使有更高的更接近的值,它也只会返回下一个最小值。

If (
Hasonevalue ( TableA[A] ),
Calculate (
Max ( TableB[A] ),
Filter ( TableB, TableB[A] <= Values ( TableA[A] ) )
)
)

如果我建立一个日期/时间表,其中包含我的数据涵盖的日期范围的每一分钟(大约 2 年),我也试图找出一种方法来做到这一点,但正如我所说,我是新人到 DAX 并且无法弄清楚。

有没有什么方法可以使用类似于 (min(abs( DAX 中 excel 公式的一部分(因为它具有这些函数))在计算列中计算它?这是否可能没有现有关系,或者我会每次我想更新此报告时都必须继续在 Excel 中完成这部分工作吗?

非常感谢任何帮助。

【问题讨论】:

    标签: match powerbi dax closest fuzzy


    【解决方案1】:

    Planned 表中创建一个计算列,将其命名为ActualClosestDate 并使用此表达式:

    ActualClosestDate =
        IF (
            DATEDIFF (
                CALCULATE (
                    MAX ( TableB[Actual] ),
                    FILTER ( TableB, [Planned] >= [Actual] && TableA[Event] = TableB[Event] )
                ),
                [Planned],
                SECOND
            )
                < DATEDIFF (
                    [Planned],
                    CALCULATE (
                        MIN ( TableB[Actual] ),
                        FILTER ( TableB, [Planned] <= [Actual] && TableA[Event] = TableB[Event] )
                    ),
                    SECOND
                ),
            CALCULATE (
                MAX ( TableB[Actual] ),
                FILTER ( TableB, [Planned] >= [Actual] && TableA[Event] = TableB[Event] )
            ),
            CALCULATE (
                MIN ( TableB[Actual] ),
                FILTER ( TableB, [Planned] <= [Actual] && TableA[Event] = TableB[Event] )
            )
        )
    

    地点:

    • [Planned] 是表 A 中的计划开始日期/时间列
    • [Actual] 是表 B 中的实际开始日期/时间列

    根据您的型号更换。

    如果每个表中没有事件列,请在过滤器函数中抑制该条件。

    更新:计算三个不同的列可以提高性能,而不是在一个表达式中执行计算。

    BeforePlanned =
    DATEDIFF (
        CALCULATE (
            MAX ( TableB[Actual] ),
            FILTER ( TableB, [Planned] >= [Actual] && TableA[Event] = TableB[Event] )
        ),
        [Planned],
        SECOND
    )
    

    AfterPlanned =
    DATEDIFF (
        [Planned],
        CALCULATE (
            MIN ( TableB[Actual] ),
            FILTER ( TableB, [Planned] <= [Actual] && TableA[Event] = TableB[Event] )
        ),
        SECOND
    )
    

    ActualClosestDate =
    IF (
        [BeforePlanned] < [AfterPlanned],
        CALCULATE (
            MAX ( TableB[Actual] ),
            FILTER ( TableB, [Planned] >= [Actual] && TableA[Event] = TableB[Event] )
        ),
        CALCULATE (
            MIN ( TableB[Actual] ),
            FILTER ( TableB, [Planned] <= [Actual] && TableA[Event] = TableB[Event] )
        )
    )
    

    您甚至可以将其拆分为更多列,即获取上一个实际日期的列和获取下一个实际日期的列,然后您只需要:

    ActualClosestDate =
    IF ( [BeforePlanned] < [AfterPlanned], [PreviousActualDate], [NextActualDate] )
    

    如果这有帮助,请告诉我。

    【讨论】:

    • 谢谢。我知道这是如何工作的,我有点生气,因为它真的很简单!但是,我的数据中有 15,400 行,并且没有足够的内存来计算所有这些行,这对我来说有点令人惊讶。我会去调查这个问题的解决方案。也许只是更多的内存......
    • @NeilScrivener,一种解决方案可能是在两个表之间创建关系,但我可以看到两个表中没有公共列。您可以尝试将表达式拆分为几列。
    • 好建议 - 这确实有帮助。它现在可以工作,但在刷新查询时非常慢。仍然希望从长远来看,它会比每次我想这样做时都进行所有手动匹配工作更快。
    • @NeilScrivener,我认为您应该找到一种方法来关联源中的日期(同时进行 ETL)。如果您的问题已解决,您可以mark the answer as correct
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-29
    • 1970-01-01
    • 1970-01-01
    • 2021-04-01
    • 2011-03-01
    • 2015-03-18
    相关资源
    最近更新 更多