计算上下文是计算公式的环境, 任何 DAX 表达式都是在上下文中求值的. 行上下文和筛选上下文是 DAX 中仅有的上下文类型, 把这两种上下文称为计算上下文. 计算上下文用于限定公式计算的环境, 当上下文变化时, 相同的公式会计算出不同的结果.
一, 计算上下文
在 PowerBI 中创建的计算列是在行上下文中执行计算, 创建的度量 (meassure) 是在筛选上下文中执行计算.
行上下文是一个总是包含一行的上下文, DAX 在创建计算列时自动定义行上下文.
筛选上下文是由切片器(Slicer), 用户选择的分组字段, 关系的筛选方向等过滤器共同定义的, 而 DAX 利用筛选上下文来计算公式(度量).
二, 行上下文
行上下文仅仅存在于表的同一行中, 作用是对表中同一行的不同列, 应用公式, 逐行计算出公式的结果.
例如, 创建一个计算列 Profit, 利润的公式是由商品的 销售额 - 税额 - 成本 - 运费, DAX 公式如下所示:
Profit = FactSales[SalesAmount]-FactSales[TaxAmt]-FactSales[TotalProductCost] - FactSales[Freight]
DAX 逐行应用公式, 对于表中每一行, 都会根据公式, 把同一行上的不同列的值代入到公式中, 计算出公式的结果:
实际上, 用于执行计算的行并没有存储在公式中, 而是定义在行上下文中. 从逻辑的角度来讲, 计算列的工作流程是:
当你定义计算的列时, DAX 从表的第一行开始迭代, 首先创建了包含该行的行上下文并对表达式求值,
然后它移到第二行, 再次求出表达式;
这发生在表格中所有的行中, 如果你有 100 万行, 你可以认为 DAX 创建了 100 万行上下文来评估这个公式 100 万次.
三, 筛选上下文
创建的度量在筛选上下文中执行公式的计算, 筛选上下文是对表应用过滤器之后, 数据被筛选之后的上下文. 筛选上下文是由过滤器共同作用的, 过滤器主要有: 切片器(Slicer), 分组列和关系. DAX 的强大之处在于, DAX 不仅能够自动应用筛选上下文, 还支持修改, 清除和重定义筛选上下文.
1, 自动应用筛选上下文
在 PowerBI 的 FactSlaes 表中定义一个度量, 用于计算总的销售额:
Measure SumOfAccount = CALCULATE(SUM(FactSales[SalesAmount]))
为该度量增加一个分组列 FullName, 可以看到, 这个分组列对度量的上下文进行过滤, 使其只能计算每个 FullName 对象的销售额, 而度量自动应用筛选之后的上下文, 计算每个 FullName 的销售额:
FullName 是 DimCustomers 表的字段, 该字段能够自动过滤 FactSales 表的原因是在数据模型中, 表 DimCustomers 和表 FactSlaes 之间存在关系, 并且关系的方向是由 DimCustomer 指向 FactSales, 这说明, DimCustomers 可以过滤 FactSales:
2, 关系的方向
当关系的方向是由 A 指向 B 时, 说明 A 可以筛选 B, 而 B 不能用来筛选 A. 上图中, 表 DimCustomers 和表 FactSlaes 之间存在关系, 并且关系的方向是由 DimCustomer 指向 FactSales, 这说明, DimCustomers 可以过滤 FactSales. 我们来测试一下, FactSales 是否可以筛选 DimCustomers? 创建一个新的度量, 测试使用 FactSales 的 ProductKey 来统计用户的数量:
Measure CountCustomer = CALCULATE(COUNT(DimCustomers[CustomerKey]))
测试的结果是 Measure CountCustomers 的值是 DimCustomers 表的总数量, 也就是说, ProductKey 不能过滤 DimCustomers 表.
当把 DimCustomer 和 FactSales 之间的关系修改为双向时:
用于 FactSales 可以过滤 DimCustomers,DAX 自动应用筛选上下文, 统计每个 ProductKey 对应的客户数量:
3, 修改, 清除和重定义筛选上下文
使用 DAX 函数可以修改, 清除和重定义筛选上下文. CALCULATE()函数是 DAX 中最复杂的函数, 用于计算由指定过滤器修改的上下文中的表达式.
CALCULATE(<expression>,<filter1>,<filter2>...)
第一个参数是用于计算聚合值的度量, 后面的参数是可选的过滤器, 共有两种类型:
返回布尔值的逻辑表达式
返回表的表达式
CALCULATE 函数的复杂之处在于可变的数据上下文. 如果数据已被过滤, 则 CALCULATE 函数会更改过滤数据的上下文, 并在您指定的新上下文中计算表达式. 对于 filter 参数中使用的每个列, 将删除该列上的任何现有过滤器, 并应用 filter 参数中使用的过滤器.
参考文档:
[DAX 圣经] 第四章: 理解计算上下文(1) https://www.jianshu.com/p/d7b5fe489984
详解 CALCULATE 系列 - 基础篇 https://www.jianshu.com/p/57a9ceacf095
来源: https://www.cnblogs.com/ljhdo/p/4577188.html