DAX 获取倒数第 N 个非空白值
Posted
技术标签:
【中文标题】DAX 获取倒数第 N 个非空白值【英文标题】:DAX get N'th last non-blank value 【发布时间】:2021-05-13 06:04:59 【问题描述】:对于任何给定日期,我想获得最近 3 天的平均销售额,其中包含非空白销售额。所以我不仅需要检索最后的非空白销售(这可能很容易),而且我还需要获得倒数第二和倒数第三的销售。一般来说,我需要倒数第 N 个销售。
样本数据:
+------------+--------+--------+--------+--------+------------------+
| Date | Amount | N'th 1 | N'th 2 | N'th 3 | Expected Results |
+------------+--------+--------+--------+--------+------------------+
| 2021-02-01 | 1 | 1 | | | 1.00 |
| 2021-02-02 | 2 | 2 | 1 | | 1.50 |
| 2021-02-03 | 2 | 2 | 2 | 1 | 1.67 |
| 2021-02-04 | | 2 | 2 | 1 | 1.67 |
| 2021-02-05 | 3 | 3 | 2 | 2 | 2.33 |
| 2021-02-06 | | 3 | 2 | 2 | 2.33 |
| 2021-02-07 | | 3 | 2 | 2 | 2.33 |
| 2021-02-08 | 4 | 4 | 3 | 2 | 3.00 |
| 2021-02-09 | | 4 | 3 | 2 | 3.00 |
| 2021-02-10 | | 4 | 3 | 2 | 3.00 |
| 2021-02-11 | | 4 | 3 | 2 | 3.00 |
+------------+--------+--------+--------+--------+------------------+
N'th 1 是最后一次“非空白”销售。 N'th 2 是“最后一个”。预期结果是 N1、N2、N3 的平均值。
链接到示例数据文件以及接受答案建议的解决方案:DAX Rolling Average NonBlanks.pbix
【问题讨论】:
【参考方案1】:这是我的看法(这是一个衡量标准):
Non-blank average =
var curDate = SELECTEDVALUE(Data[Date], MAX(Data[Date]))
var nonBlankTab = FILTER(ALL(Data), NOT(ISBLANK(Data[Amount])) && Data[Date] <= curDate)
var rankedTab = FILTER ( ADDCOLUMNS ( nonBlankTab, "Rank", RANKX ( nonBlankTab, [Date] ) ), [Rank] <= 3 )
return AVERAGEX(rankedTab, [Amount])
编辑:
只是一个解释:
为选定日期计算度量值。如果不存在日期上下文,则假定为最新日期。 然后我过滤掉表,只包含不迟于 curDate 的非空白销售行 然后我对日期进行排名,以便最新的 3 个日期始终获得排名 1、2 和 3。 然后我过滤掉所有排名高于 3 的日期 最后,我计算剩余 3 个数据点的平均值。EDIT2:
我稍微简化了度量 - lastSalesDate 不是必需的。另外,根据 cmets 中的要求,我保留了第一次尝试,这是使用 TOPN 而不是 ADDCOLUMNS/RANKX/FILTER 组合的修改版本:
Non-blank average =
var curDate = SELECTEDVALUE(Data[Date], MAX(Data[Date]))
var nonBlankTab = FILTER(ALL(Data), NOT(ISBLANK(Data[Amount])) && Data[Date] <= curDate)
var rankedTab = TOPN(3, nonBlankTab, [Date])
return AVERAGEX(rankedTab, [Amount])
EDIT3:
一个更通用的度量版本,它只是从Date
列中删除过滤器,这实际上是我们所需要的。无需屠宰桌子上的所有其他过滤器:
Non-blank average =
var curDate = SELECTEDVALUE(Data[Date], MAX(Data[Date]))
var nonBlankTab = CALCULATETABLE(FILTER(Data, NOT(ISBLANK(Data[Amount])) && Data[Date] <= curDate), REMOVEFILTERS(Data[Date]))
var rankedTab = TOPN(3, nonBlankTab, [Date])
return AVERAGEX(rankedTab, [Amount])
【讨论】:
补充一下 - 使用这种方法,很容易计算任意数量的非空白销售的平均值,而无需引入额外的措施。当您过滤排名等于或低于 3 的表时,您只需在倒数第二步中更改一个值(或基于切片器)。 看起来非常优雅和有前途。我正在咀嚼它。 nonBlankTab 和rankedTab 是表格,不是吗? @PrzemyslawRemin 是的,它们是桌子。 第二次尝试很棒。如果您可以在回答中提及您的第一次尝试 - 我把它留在这里:VAR rankedTab = FILTER ( ADDCOLUMNS ( nonBlankTab, "Rank", RANKX ( nonBlankTab, [Date] ) ), [Rank] <= 3 )
因为它允许灵活性。如果一个人只想要第 N 个元素,他可以通过将
如何破解另一个东西——我想要这个 AVERAGE by product。我试过nonBlankTab = FILTER(ALLEXCEPT(Data, Data[product])
,但它不起作用。如有任何线索,我将不胜感激。【参考方案2】:
首先,创建以下 3 个措施-
n1 =
VAR current_date = MIN(your_table_name[Date])
VAR first_max_date_with_no_blank =
CALCULATE(
MAX(your_table_name[Date]),
FILTER(ALL(your_table_name), your_table_name[Date] <= current_date && your_table_name[Amount] <> BLANK())
)
RETURN
CALCULATE(
SUM(your_table_name[Amount]),
FILTER(
ALL(your_table_name),
your_table_name[Date] = first_max_date_with_no_blank
)
)
n2 =
VAR current_date = MIN(your_table_name[Date])
VAR first_max_date_with_no_blank =
CALCULATE(
MAX(your_table_name[Date]),
FILTER(ALL(your_table_name), your_table_name[Date] <= current_date && your_table_name[Amount] <> BLANK())
)
VAR second_max_date_with_no_blank =
CALCULATE(
MAX(your_table_name[Date]),
FILTER(ALL(your_table_name), your_table_name[Date] < first_max_date_with_no_blank && your_table_name[Amount] <> BLANK())
)
RETURN
CALCULATE(
SUM(your_table_name[Amount]),
FILTER(
ALL(your_table_name),
your_table_name[Date] = second_max_date_with_no_blank
)
)
n3 =
VAR current_date = MIN(your_table_name[Date])
VAR first_max_date_with_no_blank =
CALCULATE(
MAX(your_table_name[Date]),
FILTER(ALL(your_table_name), your_table_name[Date] <= current_date && your_table_name[Amount] <> BLANK())
)
VAR second_max_date_with_no_blank =
CALCULATE(
MAX(your_table_name[Date]),
FILTER(ALL(your_table_name), your_table_name[Date] < first_max_date_with_no_blank && your_table_name[Amount] <> BLANK())
)
VAR third_max_date_with_no_blank =
CALCULATE(
MAX(your_table_name[Date]),
FILTER(ALL(your_table_name), your_table_name[Date] < second_max_date_with_no_blank && your_table_name[Amount] <> BLANK())
)
RETURN
CALCULATE(
SUM(your_table_name[Amount]),
FILTER(
ALL(your_table_name),
your_table_name[Date] = third_max_date_with_no_blank
)
)
现在创建这个最终度量-
average =
VAR sum_sales = [n1] + [n2] + [n3]
VAR devide_by = IF([n1] = BLANK(),0,1) + IF([n2] = BLANK(),0,1) + IF([n3] = BLANK(),0,1)
RETURN DIVIDE(sum_sales,devide_by)
这是最终的输出-
【讨论】:
感谢您为这个答案付出的努力。这是可读的教育材料。虽然我希望解决方案更简洁。以上是关于DAX 获取倒数第 N 个非空白值的主要内容,如果未能解决你的问题,请参考以下文章