Power BI:动态计算的分组平均值 - 我可以加快速度吗?
Power BI: Dynamically Computed Grouped Averages - Can I speed this up any?
我有一群“忠实”会员来我们店里消费。这个问题在 Excel 甚至 SQL 数据库中很容易处理,但我在 Power BI 中寻找解决方案时遇到了问题。我希望我的用户能够 select 日期范围和位置以及一些其他人口统计切片器(如年龄段)。然后我想计算客户的平均每日支出 (ADS) 和每月支出 (AMS) 并将它们分组到桶中。最后,我想通过这些创建的存储桶显示各种 KPI(唯一访客、收入、旅行等)。
我尝试创建新的 tables,但是 tables 不是动态的,因为单个 ADS 和 AMS 只会在数据集刷新时重新计算。我们被告知只能使用“导入”。直接查询对我们来说不是有效的解决方案。我已经尝试过计算列,但再次遇到与 tables 相同的问题。这些列将不会使用日期 selections 重新计算。我什至尝试使用 DAX 并设置 Min/Max 日期以重新计算,但这也不起作用,因为计算列没有从报告页面到切片器的参考点。
请记住,我确实有这个功能。问题是完成所需的时间。即使只是将日期切片器调整 1 天,也需要 5 分钟以上的时间才能完成此视觉效果。我认为这对我的最终用户来说不是好兆头。我的模型是 Star Schema,只有 1 到 Many 关系,NONE 已设置为双向。包含 AMS/ADS 波段值的 table 与其他 table 没有任何关系。
这是我的衡量标准:
Rev_AMS =
VAR T1 =
SUMMARIZE(
Sales_Fact,
Loyalty_Table[Loyalty_Key], Calendar_Table[Fiscal_Period_No],
"AvgMonthSpend", [AverageMonthlySpend]
)
VAR Result =
IF(
HASONEVALUE(AMS_Bands[AMS Band]),
SWITCH(
VALUES(AMS_Bands[AMS Band]),
"<[=10=]", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] < 0)),
"[=10=]-", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 0 && [AvgMonthSpend] < 15)),
"-", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 15 && [AvgMonthSpend] < 30)),
"-", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 30 && [AvgMonthSpend] < 50)),
"-", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 50 && [AvgMonthSpend] < 75)),
"-0", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 75 && [AvgMonthSpend] < 100)),
"0-0", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 100 && [AvgMonthSpend] < 150)),
"0-0", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 150 && [AvgMonthSpend] < 200)),
"0-0", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 200 && [AvgMonthSpend] < 300)),
"0+", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 300))
),
[Rev]
)
RETURN Result
加入这一指标的其他措施是:
Rev = SUM(Sales_Fact[Revenue])
AverageMonthlySpend = DIVIDE([Rev],[MonthlyTrip],BLANK())
MonthlyTrip =
Var T =
SUMMARIZE(
Sales_Fact,
Calendar_Table[Fiscal_Period_No], Sales_Fact[Organization_Key],
"Trip", [UniqueGuest]
)
Var Result =
SUMX(
T,
[Trip]
)
RETURN Result
UniqueGuest = DISTINCTCOUNT(Sales_Fact[Loyalty_Key])
我的问题:是否有 better/faster 方法可以实现此目的?
为了成为一个有效的解决方案,我需要保持基于用户切片器 selection 的 ADS/AMS 的动态计算,同时加快计算速度(最好显着,但我会采取什么我可以得到)。
提前致谢。
试试这些措施,让我知道是否提高了性能:
Rev_AMS =
VAR T1 =
ADDCOLUMNS (
SUMMARIZE (
Sales_Fact,
Loyalty_Table[Loyalty_Key],
Calendar_Table[Fiscal_Period_No]
),
"AvgMonthSpend", [AverageMonthlySpend]
)
VAR Result =
IF (
ISINSCOPE ( AMS_Bands[AMS Band] ),
SWITCH (
SELECTEDVALUE ( AMS_Bands[AMS Band] ),
"<[=10=]", CALCULATE ( [Rev], FILTER ( T1, [AvgMonthSpend] < 0 ) ),
"[=10=]-",
CALCULATE ( [Rev], FILTER ( T1, [AvgMonthSpend] >= 0 && [AvgMonthSpend] < 15 ) ),
"-",
CALCULATE (
[Rev],
FILTER ( T1, [AvgMonthSpend] >= 15 && [AvgMonthSpend] < 30 )
),
"-",
CALCULATE (
[Rev],
FILTER ( T1, [AvgMonthSpend] >= 30 && [AvgMonthSpend] < 50 )
),
"-",
CALCULATE (
[Rev],
FILTER ( T1, [AvgMonthSpend] >= 50 && [AvgMonthSpend] < 75 )
),
"-0",
CALCULATE (
[Rev],
FILTER ( T1, [AvgMonthSpend] >= 75 && [AvgMonthSpend] < 100 )
),
"0-0",
CALCULATE (
[Rev],
FILTER ( T1, [AvgMonthSpend] >= 100 && [AvgMonthSpend] < 150 )
),
"0-0",
CALCULATE (
[Rev],
FILTER ( T1, [AvgMonthSpend] >= 150 && [AvgMonthSpend] < 200 )
),
"0-0",
CALCULATE (
[Rev],
FILTER ( T1, [AvgMonthSpend] >= 200 && [AvgMonthSpend] < 300 )
),
"0+", CALCULATE ( [Rev], FILTER ( T1, [AvgMonthSpend] >= 300 ) )
),
[Rev]
)
RETURN
Result
MonthlyTrip =
VAR T =
ADDCOLUMNS (
SUMMARIZE (
Sales_Fact,
Calendar_Table[Fiscal_Period_No],
Sales_Fact[Organization_Key]
),
"Trip", [UniqueGuest]
)
VAR Result =
SUMX ( T, [Trip] )
RETURN
Result
UniqueGuest =
SUMX (
DISTINCT ( Sales_Fact[Loyalty_Key] ),
1
)
我不能使用注释,因为那样会限制可读性,所以必须添加另一个答案:
以下是您应始终遵循的一些建议。
- 仅使用 SUMMARIZE 进行 groupby 操作,不要使用它来添加新列,这是一个次优函数,几乎总是会生成具有更大数据缓存的更复杂的查询计划,始终使用 ADDCOLUMNS 添加新列.这是显示差异的图像 https://ibb.co/1Q7SSgB(注意 Rows header 下数据缓存报告的行)
- 大多数时候你只想知道 HASONEVALUE 中使用的列是否被用于分组,所以只需用更优化的 ISINSCOPE 替换它,请注意两者有不同的用例,但在大多数情况下 ISINSCOPE 是要走的路
- DISTINCTCOUNT 是一个 non-additive 度量,对于任何类型的分析工具来说都是一个复杂的函数,当过滤器上下文频繁变化时,DAX 引擎会生成如此多的存储引擎查询,从而降低性能,在另一方面,SUMX 速度更快,因为它将从存储引擎中获取单个数据缓存,然后公式引擎将对其进行迭代,从而节省大量时间。
这是我几个月前解决的 post,它会让您了解为什么 SUMX 构造比 DISTINCTCOUNT 更快 https://forum.enterprisedna.co/t/dax-calculation-based-on-previous-day-and-a-constant-value/14948/2
我有一群“忠实”会员来我们店里消费。这个问题在 Excel 甚至 SQL 数据库中很容易处理,但我在 Power BI 中寻找解决方案时遇到了问题。我希望我的用户能够 select 日期范围和位置以及一些其他人口统计切片器(如年龄段)。然后我想计算客户的平均每日支出 (ADS) 和每月支出 (AMS) 并将它们分组到桶中。最后,我想通过这些创建的存储桶显示各种 KPI(唯一访客、收入、旅行等)。
我尝试创建新的 tables,但是 tables 不是动态的,因为单个 ADS 和 AMS 只会在数据集刷新时重新计算。我们被告知只能使用“导入”。直接查询对我们来说不是有效的解决方案。我已经尝试过计算列,但再次遇到与 tables 相同的问题。这些列将不会使用日期 selections 重新计算。我什至尝试使用 DAX 并设置 Min/Max 日期以重新计算,但这也不起作用,因为计算列没有从报告页面到切片器的参考点。
请记住,我确实有这个功能。问题是完成所需的时间。即使只是将日期切片器调整 1 天,也需要 5 分钟以上的时间才能完成此视觉效果。我认为这对我的最终用户来说不是好兆头。我的模型是 Star Schema,只有 1 到 Many 关系,NONE 已设置为双向。包含 AMS/ADS 波段值的 table 与其他 table 没有任何关系。
这是我的衡量标准:
Rev_AMS =
VAR T1 =
SUMMARIZE(
Sales_Fact,
Loyalty_Table[Loyalty_Key], Calendar_Table[Fiscal_Period_No],
"AvgMonthSpend", [AverageMonthlySpend]
)
VAR Result =
IF(
HASONEVALUE(AMS_Bands[AMS Band]),
SWITCH(
VALUES(AMS_Bands[AMS Band]),
"<[=10=]", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] < 0)),
"[=10=]-", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 0 && [AvgMonthSpend] < 15)),
"-", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 15 && [AvgMonthSpend] < 30)),
"-", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 30 && [AvgMonthSpend] < 50)),
"-", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 50 && [AvgMonthSpend] < 75)),
"-0", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 75 && [AvgMonthSpend] < 100)),
"0-0", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 100 && [AvgMonthSpend] < 150)),
"0-0", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 150 && [AvgMonthSpend] < 200)),
"0-0", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 200 && [AvgMonthSpend] < 300)),
"0+", CALCULATE([Rev], FILTER(T1, [AvgMonthSpend] >= 300))
),
[Rev]
)
RETURN Result
加入这一指标的其他措施是:
Rev = SUM(Sales_Fact[Revenue])
AverageMonthlySpend = DIVIDE([Rev],[MonthlyTrip],BLANK())
MonthlyTrip =
Var T =
SUMMARIZE(
Sales_Fact,
Calendar_Table[Fiscal_Period_No], Sales_Fact[Organization_Key],
"Trip", [UniqueGuest]
)
Var Result =
SUMX(
T,
[Trip]
)
RETURN Result
UniqueGuest = DISTINCTCOUNT(Sales_Fact[Loyalty_Key])
我的问题:是否有 better/faster 方法可以实现此目的?
为了成为一个有效的解决方案,我需要保持基于用户切片器 selection 的 ADS/AMS 的动态计算,同时加快计算速度(最好显着,但我会采取什么我可以得到)。
提前致谢。
试试这些措施,让我知道是否提高了性能:
Rev_AMS =
VAR T1 =
ADDCOLUMNS (
SUMMARIZE (
Sales_Fact,
Loyalty_Table[Loyalty_Key],
Calendar_Table[Fiscal_Period_No]
),
"AvgMonthSpend", [AverageMonthlySpend]
)
VAR Result =
IF (
ISINSCOPE ( AMS_Bands[AMS Band] ),
SWITCH (
SELECTEDVALUE ( AMS_Bands[AMS Band] ),
"<[=10=]", CALCULATE ( [Rev], FILTER ( T1, [AvgMonthSpend] < 0 ) ),
"[=10=]-",
CALCULATE ( [Rev], FILTER ( T1, [AvgMonthSpend] >= 0 && [AvgMonthSpend] < 15 ) ),
"-",
CALCULATE (
[Rev],
FILTER ( T1, [AvgMonthSpend] >= 15 && [AvgMonthSpend] < 30 )
),
"-",
CALCULATE (
[Rev],
FILTER ( T1, [AvgMonthSpend] >= 30 && [AvgMonthSpend] < 50 )
),
"-",
CALCULATE (
[Rev],
FILTER ( T1, [AvgMonthSpend] >= 50 && [AvgMonthSpend] < 75 )
),
"-0",
CALCULATE (
[Rev],
FILTER ( T1, [AvgMonthSpend] >= 75 && [AvgMonthSpend] < 100 )
),
"0-0",
CALCULATE (
[Rev],
FILTER ( T1, [AvgMonthSpend] >= 100 && [AvgMonthSpend] < 150 )
),
"0-0",
CALCULATE (
[Rev],
FILTER ( T1, [AvgMonthSpend] >= 150 && [AvgMonthSpend] < 200 )
),
"0-0",
CALCULATE (
[Rev],
FILTER ( T1, [AvgMonthSpend] >= 200 && [AvgMonthSpend] < 300 )
),
"0+", CALCULATE ( [Rev], FILTER ( T1, [AvgMonthSpend] >= 300 ) )
),
[Rev]
)
RETURN
Result
MonthlyTrip =
VAR T =
ADDCOLUMNS (
SUMMARIZE (
Sales_Fact,
Calendar_Table[Fiscal_Period_No],
Sales_Fact[Organization_Key]
),
"Trip", [UniqueGuest]
)
VAR Result =
SUMX ( T, [Trip] )
RETURN
Result
UniqueGuest =
SUMX (
DISTINCT ( Sales_Fact[Loyalty_Key] ),
1
)
我不能使用注释,因为那样会限制可读性,所以必须添加另一个答案:
以下是您应始终遵循的一些建议。
- 仅使用 SUMMARIZE 进行 groupby 操作,不要使用它来添加新列,这是一个次优函数,几乎总是会生成具有更大数据缓存的更复杂的查询计划,始终使用 ADDCOLUMNS 添加新列.这是显示差异的图像 https://ibb.co/1Q7SSgB(注意 Rows header 下数据缓存报告的行)
- 大多数时候你只想知道 HASONEVALUE 中使用的列是否被用于分组,所以只需用更优化的 ISINSCOPE 替换它,请注意两者有不同的用例,但在大多数情况下 ISINSCOPE 是要走的路
- DISTINCTCOUNT 是一个 non-additive 度量,对于任何类型的分析工具来说都是一个复杂的函数,当过滤器上下文频繁变化时,DAX 引擎会生成如此多的存储引擎查询,从而降低性能,在另一方面,SUMX 速度更快,因为它将从存储引擎中获取单个数据缓存,然后公式引擎将对其进行迭代,从而节省大量时间。
这是我几个月前解决的 post,它会让您了解为什么 SUMX 构造比 DISTINCTCOUNT 更快 https://forum.enterprisedna.co/t/dax-calculation-based-on-previous-day-and-a-constant-value/14948/2