第12篇:DAX 高级计算与性能优化
1. DAX 计算上下文深度理解
1.1 行上下文
遍历表的每一行,可访问当前行的字段值:
dax
// 计算列中使用行上下文
利润率 = Sales[Profit] / Sales[Amount]
// 迭代函数中使用行上下文
总利润 = SUMX(Sales, Sales[Quantity] * Sales[UnitPrice] - Sales[Cost])
1.2 筛选上下文
由外部筛选器、切片器、关系决定:
dax
// CALCULATE 修改筛选上下文
大额订单数 =
CALCULATE(
COUNTROWS(Sales),
Sales[Amount] > 10000
)
1.3 上下文转换
行上下文 → 筛选上下文:
dax
// 在迭代函数中使用度量值
总销售额 = SUMX(Sales, [销售额]) // 自动上下文转换
// 等价于
总销售额 = SUMX(Sales, CALCULATE(SUM(Sales[Amount])))
2. CALCULATE 高级用法
2.1 修改筛选器
dax
// ALL - 移除筛选
总占比 =
DIVIDE(
[销售额],
CALCULATE([销售额], ALL(Sales))
)
// ALLEXCEPT - 保留指定列
类别占比 =
DIVIDE(
[销售额],
CALCULATE([销售额], ALLEXCEPT(Sales, Product[Category]))
)
// ALLSELECTED - 基于用户选择
视觉对象占比 =
DIVIDE(
[销售额],
CALCULATE([销售额], ALLSELECTED(Sales))
)
2.2 添加筛选器
dax
// 添加新筛选
电子产品销售额 =
CALCULATE(
[销售额],
Product[Category] = "电子产品"
)
// 复合筛选
高价值订单 =
CALCULATE(
[销售额],
Sales[Amount] > 1000,
Product[Category] = "电子产品" || Product[Category] = "家居"
)
2.3 筛选器覆盖规则
dax
// 相同列的筛选器会覆盖
度量值 =
CALCULATE(
[销售额],
Product[Category] = "电子产品", // 会覆盖外部筛选
ALL(Product[Category])
)
// 不同列的筛选器会叠加
度量值 =
CALCULATE(
[销售额],
Product[Category] = "电子产品",
Product[Color] = "黑色"
)
3. 时间智能函数详解
3.1 标准时间智能
dax
// 累计年初至今
YTD销售额 = TOTALYTD([销售额], Date[Date])
// 等价写法
YTD销售额 =
CALCULATE(
[销售额],
DATESYTD(Date[Date])
)
// 上年同期
去年同期销售额 =
CALCULATE(
[销售额],
SAMEPERIODLASTYEAR(Date[Date])
)
// 上月
上月销售额 =
CALCULATE(
[销售额],
DATEADD(Date[Date], -1, MONTH)
)
3.2 灵活时间计算
dax
// 最近N天
最近30天销售额 =
CALCULATE(
[销售额],
DATESINPERIOD(
Date[Date],
MAX(Date[Date]),
-30,
DAY
)
)
// N个季度移动平均
季度移动平均 =
CALCULATE(
AVERAGEX(
VALUES(Date[Quarter]),
[销售额]
),
DATESINPERIOD(
Date[Date],
MAX(Date[Date]),
-4,
QUARTER
)
)
3.3 工作日计算
dax
// 计算工作日数
工作日数 =
CALCULATE(
COUNTROWS(Date),
Date[IsWorkday] = TRUE,
DATESINPERIOD(Date[Date], MAX(Date[Date]), -1, MONTH)
)
// 工作日平均销售额
工作日日均 =
DIVIDE(
[月销售额],
[工作日数]
)
4. 高级聚合函数
4.1 SUMX / AVERAGEX 迭代
dax
// 加权平均单价
加权平均单价 =
DIVIDE(
SUMX(Sales, Sales[Quantity] * Sales[UnitPrice]),
SUM(Sales[Quantity])
)
// 迭代计算利润
总利润 =
SUMX(
Sales,
Sales[Quantity] * (Sales[UnitPrice] - Sales[UnitCost])
)
4.2 MAXX / MINX 最值计算
dax
// 最大单笔订单
最大订单金额 = MAXX(Sales, Sales[Amount])
// 各产品最大日销量
产品最大日销量 =
MAXX(
VALUES(Date[Date]),
CALCULATE(SUM(Sales[Quantity]))
)
4.3 RANKX 排名
dax
// 产品销售额排名
产品排名 =
RANKX(
ALL(Product[ProductName]),
[销售额],
,
DESC,
DENSE
)
// 分类内排名
分类内排名 =
RANKX(
ALLEXCEPT(Product, Product[Category]),
[销售额],
,
DESC,
DENSE
)
5. 筛选器函数进阶
5.1 FILTER vs 直接筛选
dax
// 方式1:直接筛选(推荐)
销售额A =
CALCULATE(
[销售额],
Product[Category] = "电子产品"
)
// 方式2:FILTER(复杂逻辑)
销售额B =
CALCULATE(
[销售额],
FILTER(
Product,
Product[Category] = "电子产品" && Product[Price] > 100
)
)
5.2 KEEPFILTERS
保持现有筛选器,而非覆盖:
dax
// 不使用 KEEPFILTERS(会覆盖)
错误计算 =
CALCULATE(
[销售额],
Product[Color] IN {"红色", "蓝色"}
)
// 使用 KEEPFILTERS(叠加)
正确计算 =
CALCULATE(
[销售额],
KEEPFILTERS(Product[Color] IN {"红色", "蓝色"})
)
5.3 TREATAS
虚拟关系,无需物理关系:
dax
// 假设有一个与事实表无关系的预算表
预算达成率 =
DIVIDE(
[销售额],
CALCULATE(
SUM(Budget[Amount]),
TREATAS(VALUES(Product[Category]), Budget[Category]),
TREATAS(VALUES(Date[Month]), Budget[Month])
)
)
6. 性能优化技巧
6.1 使用 DAX Studio 分析
dax
// 查看查询计划和存储引擎查询
EVALUATE
CALCULATETABLE(
VALUES(Product[Category]),
[销售额] > 100000
)
6.2 减少迭代次数
dax
// 慢 - 迭代整个表
总金额1 = SUMX(Sales, Sales[Quantity] * Sales[UnitPrice])
// 快 - 预先计算列
// 在 Power Query 中添加 Amount = Quantity * UnitPrice
总金额2 = SUM(Sales[Amount])
6.3 避免复杂计算列
dax
// 计算列(性能差)
相关产品数 =
CALCULATE(
COUNTROWS(Product),
Sales[ProductID] = EARLIER(Sales[ProductID])
)
// 度量值(性能好)
相关产品数 =
CALCULATE(
COUNTROWS(Product),
FILTER(
ALL(Sales),
Sales[ProductID] = SELECTEDVALUE(Sales[ProductID])
)
)
6.4 变量优化
dax
// 不使用变量(重复计算)
增长率 =
DIVIDE(
[销售额] - CALCULATE([销售额], SAMEPERIODLASTYEAR(Date[Date])),
CALCULATE([销售额], SAMEPERIODLASTYEAR(Date[Date]))
)
// 使用变量(计算一次)
增长率 =
VAR CurrentSales = [销售额]
VAR LastYearSales = CALCULATE([销售额], SAMEPERIODLASTYEAR(Date[Date]))
RETURN
DIVIDE(CurrentSales - LastYearSales, LastYearSales)
7. 常见性能问题
7.1 高基数列问题
| 问题 | 解决方案 |
|---|---|
| 高基数列 | 减少使用,或分区处理 |
| DateTime 列 | 使用整数日期键 |
| GUID 列 | 避免用于关系 |
7.2 复杂筛选器
dax
// 慢 - 复杂筛选
慢查询 =
CALCULATE(
[销售额],
FILTER(
Product,
LEN(Product[Name]) > 10
)
)
// 快 - 简化筛选
快查询 =
CALCULATE(
[销售额],
Product[NameLength] > 10 // 预计算列
)
7.3 过度使用度量值
dax
// 每个度量值都独立计算
总度量值1 = [销售额] + [成本] + [利润]
// 改用变量合并计算
总度量值2 =
VAR Sales = [销售额]
VAR Cost = [成本]
VAR Profit = [利润]
RETURN
Sales + Cost + Profit
8. 调试技巧
8.1 逐步验证
dax
// 使用变量分段调试
调试度量值 =
VAR Step1 = CALCULATE([销售额], ALL(Date))
VAR Step2 = CALCULATE([销售额], ALLEXCEPT(Date, Date[Year]))
VAR Step3 = [销售额]
RETURN
Step3 // 逐步替换检查
8.2 查看筛选上下文
dax
// 返回当前筛选条件
当前筛选 =
CONCATENATEX(
FILTER(
ALLSELECTED(Product[Category]),
ISFILTERED(Product[Category])
),
Product[Category],
", "
)
9. 最佳实践总结
✅ 优先使用变量
✅ 简化筛选器逻辑
✅ 减少迭代范围
✅ 用度量值替代计算列
✅ 使用 DAX Studio 分析
✅ 时间智能需有连续日期表
❌ 避免嵌套 CALCULATE
❌ 避免大表迭代
❌ 避免高基数计算列
❌ 避免过度度量值依赖
10. 小结
本篇介绍了 DAX 高级计算:
| 主题 | 要点 |
|---|---|
| 计算上下文 | 行上下文 vs 筛选上下文 |
| CALCULATE | 修改、添加、覆盖筛选 |
| 时间智能 | YTD、SAMEPERIODLASTYEAR |
| 迭代函数 | SUMX、RANKX、FILTER |
| 性能优化 | 变量、减少迭代、避免计算列 |
下一篇,我们将探讨高级可视化与自定义图表。