DAX计算需求:按客户-产品组合统计使用量增量增长
解决DAX计算客户-产品组合使用量增量的问题
问题需求
在数据表中新增计算列,显示每行对应CustomerName和ProductName唯一组合的使用量,相对于该组合最早日期使用量的增量增长。
样本数据
| CustomerName | ProductName | 使用量(Usage) | 日期(Date) |
|---|---|---|---|
| CustomerA | service A | 2570 | 2023-06-01 |
| CustomerA | service A | 2539 | 2023-07-01 |
| CustomerA | service A | 2579 | 2023-08-01 |
| CustomerA | service A | 2581 | 2023-09-01 |
| CustomerB | Service B | 153 | 2023-06-01 |
| CustomerB | Service B | 406 | 2023-07-01 |
| CustomerB | Service B | 603 | 2023-08-01 |
| CustomerB | Service C | 15 | 2023-06-01 |
| CustomerB | Service C | 16 | 2023-07-01 |
| CustomerB | Service C | 13 | 2023-08-01 |
原代码问题
尝试的DAX查询无法正确计算增量,非最早日期行的基准值(SoYValue)被计算为0:
Calc_IncGrowthOverTime = VAR CurrentCustName = [CustomerName] VAR CurrentWorkLoad = [WorkloadName] VAR EarliestDate = CALCULATE(MIN('Table1'[Date]), ALL('Table1'), 'Table1'[CustomerName] = CurrentCustName, 'Table1'[WorkloadName] = CurrentWorkLoad) VAR SoYValue = CALCULATE(MIN('Table1'[Usage]), 'Table1'[Date] = EarliestDate, 'Table1'[CustomerName] = CurrentCustName, 'Table1'[WorkloadName] = CurrentWorkLoad) RETURN [Usage] - SoYValue
错误原因
- 列名不匹配:样本数据中产品列名为
ProductName,但代码中错误使用WorkloadName,导致无法匹配到正确的产品组合,基准值计算为空,DAX中空值参与减法会被视为0。 - 上下文控制不当:
ALL('Table1')清除了所有筛选上下文,后续筛选逻辑可优化以避免不必要的上下文重置。
正确DAX计算列公式
简洁优化版
Calc_IncGrowthOverTime = VAR CurrentCustomer = [CustomerName] VAR CurrentProduct = [ProductName] -- 获取当前客户-产品组合的最早日期对应的使用量 VAR BaseUsage = CALCULATE( MIN('Table1'[使用量(Usage)]), ALLEXCEPT('Table1', 'Table1'[CustomerName], 'Table1'[ProductName]), 'Table1'[Date] = CALCULATE(MIN('Table1'[Date]), ALLEXCEPT('Table1', 'Table1'[CustomerName], 'Table1'[ProductName])) ) RETURN [使用量(Usage)] - BaseUsage
兼容基础版(无需依赖ALLEXCEPT)
Calc_IncGrowthOverTime = VAR BaseUsage = CALCULATE( MIN('Table1'[使用量(Usage)]), FILTER( ALL('Table1'), 'Table1'[CustomerName] = EARLIER('Table1'[CustomerName]) && 'Table1'[ProductName] = EARLIER('Table1'[ProductName]) && 'Table1'[Date] = CALCULATE(MIN('Table1'[Date]), FILTER(ALL('Table1'), 'Table1'[CustomerName] = EARLIER('Table1'[CustomerName]) && 'Table1'[ProductName] = EARLIER('Table1'[ProductName]))) ) ) RETURN [使用量(Usage)] - BaseUsage
验证结果
执行正确公式后,得到的增量值如下:
| CustomerName | ProductName | 使用量(Usage) | 日期(Date) | Calc_IncGrowthOverTime |
|---|---|---|---|---|
| CustomerA | service A | 2570 | 2023-06-01 | 0 |
| CustomerA | service A | 2539 | 2023-07-01 | -31 |
| CustomerA | service A | 2579 | 2023-08-01 | 9 |
| CustomerA | service A | 2581 | 2023-09-01 | 11 |
| CustomerB | Service B | 153 | 2023-06-01 | 0 |
| CustomerB | Service B | 406 | 2023-07-01 | 253 |
| CustomerB | Service B | 603 | 2023-08-01 | 450 |
| CustomerB | Service C | 15 | 2023-06-01 | 0 |
| CustomerB | Service C | 16 | 2023-07-01 | 1 |
| CustomerB | Service C | 13 | 2023-08-01 | -2 |
公式说明
ALLEXCEPT('Table1', 'Table1'[CustomerName], 'Table1'[ProductName]):保留当前行的CustomerName和ProductName筛选上下文,清除其他所有筛选,确保仅计算当前组合的数据。CALCULATE(MIN('Table1'[Date]), ...):获取当前客户-产品组合的最早日期,再基于该日期提取对应的基准使用量。EARLIER()函数:引用外部行上下文的CustomerName和ProductName值,确保筛选范围精准匹配当前行的组合。
内容的提问来源于stack exchange,提问作者Jamie Wheeldon
相关产品推荐
相关产品推荐

