计算列 - 从过滤器的日期范围过滤 MAX

Calculated Column - Filtering MAX on date range from filter

考虑以下 tables - 一台打印机,另一台来自仪表读数的页数:

Printers
+------------+---------+--------+
| Printer ID |  Make   | Model  |
+------------+---------+--------+
|          1 | Xerox   | ABC123 |
|          2 | Brother | DEF456 |
|          3 | Xerox   | ABC123 |
+------------+---------+--------+


Meter Read
+-------+------------+-----------+------------+
| Index | Printer ID | Poll Date | Mono Pages |
+-------+------------+-----------+------------+
|     1 |          1 | 1/1/2019  |       1000 |
|     2 |          2 | 1/1/2019  |        800 |
|     3 |          3 | 1/1/2019  |      33000 |
|     4 |          1 | 1/2/2019  |       1100 |
|     5 |          2 | 1/2/2019  |        850 |
|     6 |          3 | 1/2/2019  |      34000 |
|     7 |          1 | 1/3/2019  |       1200 |
|     8 |          2 | 1/3/2019  |        900 |
|     9 |          3 | 1/3/2019  |      35000 |
|    10 |          1 | 1/4/2019  |       1400 |
|    11 |          2 | 1/4/2019  |        950 |
|    12 |          3 | 1/4/2019  |      36000 |
|    13 |          1 | 1/5/2019  |       1800 |
|    14 |          2 | 1/5/2019  |       1000 |
|    15 |          3 | 1/5/2019  |      36500 |
|    16 |          1 | 1/6/2019  |       2000 |
|    17 |          2 | 1/6/2019  |       1050 |
|    18 |          3 | 1/6/2019  |      37500 |
|    19 |          1 | 1/7/2019  |       2100 |
|    20 |          2 | 1/7/2019  |       1100 |
|    21 |          3 | 1/7/2019  |      39000 |
|    22 |          1 | 1/8/2019  |       2200 |
|    23 |          2 | 1/8/2019  |       1150 |
|    24 |          3 | 1/8/2019  |      40000 |
+-------+------------+-----------+------------+

在我的 Power BI 报告中,我有一个日期 table:

Dates = CALENDAR(DATE(2019, 1, 1), DATE(2019, 1, 31))

我用作切片器。目标是在切片器的日期范围内以 Mono Pages 的增量结束。我能够通过 Meter Read table:

上相当复杂的计算列来获取每个仪表读数之间的差异
PagesSinceLastPoll = 
IF(
    ISBLANK(
        LOOKUPVALUE(
            'Meter Read'[Mono Pages],
            'Meter Read'[Index], CALCULATE(
                MAX(
                    'Meter Read'[Index]
                ), FILTER(
                    'Meter Read',
                    'Meter Read'[Index] < EARLIER('Meter Read'[Index])
                        && 'Meter Read'[Printer ID] = EARLIER('Meter Read'[Printer ID] )
                )
            )
        )
    ),
    BLANK(),
    'Meter Read'[Mono Pages] - 
    LOOKUPVALUE(
        'Meter Read'[Mono Pages],
        'Meter Read'[Index], CALCULATE(
            MAX(
                'Meter Read'[Index]
            ), FILTER(
                'Meter Read',
                'Meter Read'[Index] < EARLIER('Meter Read'[Index])
                    && 'Meter Read'[Printer ID] = EARLIER('Meter Read'[Printer ID] )
            )
        )
    )
)

但是超过 10,000+ 行的性能很差。我想在过滤的日期范围内获取设备的最大值和最小值,然后只减去,但我很难获得正确的值。到目前为止,我的 DAX 不断让我从整个 table 中获取最大值,而不是根据我的切片器中的日期过滤的 table。到目前为止,我尝试过的所有内容都是一些变体:

MaxInRange =
CALCULATE (
    MAX ( 'Meter Read'[Mono Pages] ),
    FILTER ( 'Meter Read', 'Meter Read'[Printer ID] = Printers[Printer ID] )
)

总结一下:如果我有一个从 2019 年 1 月 2 日开始到 2019 年 1 月 5 日结束的切片器,打印机 ID 1 的最大值应该是 1800,而不是 2200。

想法?

计算列可以像这样更高效地完成:

PagesSinceLastPoll = 
VAR PrevRow =
    TOPN(1,
        FILTER('Meter Read',
            'Meter Read'[PrinterID] = EARLIER('Meter Read'[PrinterID]) &&
            'Meter Read'[PollDate] < EARLIER('Meter Read'[PollDate])
        ),
        'Meter Read'[PollDate]
    )
RETURN 'Meter Read'[MonoPages] - SELECTCOLUMNS(PrevRow, "Pages", 'Meter Read'[MonoPages])

使用它,两个日期之间的页数可以只对这些日期的这一列求和。


如果您想跳过它并直接进行测量,请尝试这样的操作:

PagesInPeriod = 
VAR StartDate = FIRSTDATE(Dates[Date])
VAR EndDate = LASTDATE(Dates[Date])
RETURN
SUMX(
    VALUES('Meter Read'[PrinterID]),
    CALCULATE(
        MAX('Meter Read'[MonoPages]),
        Dates[Date] = EndDate
    )
    -
    CALCULATE(
        MAX('Meter Read'[MonoPages]),
        Dates[Date] < StartDate
    )
)

请注意,如果您使用 Dates[Date] = StartDate,那么您将被关闭。您想要计算第一个包含日期之前的最大页数。


这两种方法应该给出相同的结果:

Alexis 的措施是处理此问题的正确方法(非常感谢!),但我做了一个非常小的修改。由于可能没有在结束日期进行读数,我们需要在该日期或之前查看,否则它会将结束日期的最大值视为零。最终代码变为:

PagesInPeriod = 
VAR StartDate = FIRSTDATE(Dates[Date])
VAR EndDate = LASTDATE(Dates[Date])
RETURN
SUMX(
    VALUES('Meter Read'[PrinterID]),
    CALCULATE(
        MAX('Meter Read'[MonoPages]),
        Dates[Date] <= EndDate
    )
    -
    CALCULATE(
        MAX('Meter Read'[MonoPages]),
        Dates[Date] < StartDate
    )
)