PowerBI/DAX之初识筛选上下文

DAX的计值环境是由数据模型、筛选上下文以及行上下文所构成的,而DAX表达式的整个计值流程都依赖于计值环境。因此,对计值环境的理解决定着你对DAX的掌握程度,可见计值环境的重要性。那么本篇文章就将带领你们初步认识筛选上下文,并对一些相关的概念进行介绍,为以后的学习打下良好的基础。


为了更方便的介绍,我们先来看一些概念的简单介绍:

  • 计值上下文可以分为:筛选上下文与行上下文

  • 计值环境:由存在的数据模型、筛选上下文以及行上下文所构成

  • 可见数据:能参与计算的数据,也可简单理解成被筛选后的数据

  • 初始筛选器:数据透视表(矩阵)的行列标签、筛选页字段、切片器、钻取、图表联动

  • 筛选上下文:所有筛选器经过交互作用后,最终得到的可见数据

  • 外部计值环境:对某个函数而言,将在其开始计算时就已存在的计值环境称为外部计值环境

下面我们先来直接观察一下,看看筛选上下文究竟指的是什么,然后再进一步介绍筛选上下文的生成方式。为了直接观察到筛选上下文,我们可以先对现有的数据创建一个普通的透视表,然后把产品名称放入透视表的行字段并把利润放入透视表的值字段,然后双击透视表中某个产品的利润汇总值,即可查看明细数据,这些明细数据就是我们所说的筛选上下文了。具体的操作见下图:

从上图可以知道,所谓的筛选上下文其实就是指的基础表被筛选器筛选后的数据,即可见数据,所有的DAX表达式都是在可见数据的基础上进行计值的。当不存在任何筛选器的时候,可见数据为所有数据,那么这时的筛选上下文也为所有数据。

我们现在已经知道筛选上下文指的是什么了,当它的面纱被揭开后其实是很简单的一个东西,但为什么很多人都觉得筛选上下文很难理解,很难掌握呢?这其实就涉及到了一个东西,那就是筛选上下文的生成方式。我们在上图中所看到的透视表里U盘行标签的筛选上下文其实是最终结果,而这个最终结果要经过几个步骤才能得到,所以我们不仅要了解筛选上下文是什么东西,更关键的是要理解它的生成方式。筛选上下文的生成方式如下:

由上面的流程可以知道,若干标准筛选器与固化筛选器经过交互作用后可以得到一个筛选器组合,然后这个筛选器组合再去筛选数据模型中的各个基础表,所有基础表的可见数据组成了当前计值环境下的筛选上下文。其中,当外部只有一个筛选器时,筛选器组合就等于这个筛选器。简单来说就是,多个筛选器可以合并成一个筛选器,只有一个筛选器时自然就不用合并了,或者说合并后仍然等于自身。

因此,我们只需要把下面这两个过程搞清楚,就可以彻底掌握筛选上下文了:

  • 多个筛选器是如何合并成一个筛选器(筛选器间的交互方式)
  • 筛选器是如何筛选数据的(筛选器在表间关系上的传递)

筛选上下文在严格意义上其实是指的数据模型中所有基础表的可见数据,但一般我们只需要对某个表的数据进行聚合或计值,因此一般意义上的筛选上下文指的是我们需要进行聚合计算的那个表的可见数据。此外,若直接以筛选上下文的形式来理解计值流程的话会不太方便,因为筛选上下文其实是由若干筛选器经过交互与筛选后所生成的,当我们要修改筛选上下文时其实是通过修改现有的筛选器或筛选器组合来完成的,故别的资料上所说的筛选上下文可能会与我描述的不一致,其它资料上所说的筛选上下文可能指的是现有的筛选器或者是筛选器组合,这一点需要注意一下。

在筛选上下文的生成步骤中,最难以理解的其实是筛选器之间的交互方式,以及筛选器在表间关系上的传递等等,而这些内容都会在后续的文章中介绍。现在我们只需要记住筛选上下文的定义以及它的生成方式,并搞清楚筛选器有哪些类别与来源就可以了。

首先,筛选器的类别有两种,一种是标准筛选器,另一种则是固化筛选器。其次,筛选器的来源大概有以下几种:

  • 初始筛选器:数据透视表(矩阵)的行列标签、筛选页字段、切片器、钻取、图表联动
  • CALCULATE或CALCULATETABLE函数所提供的内部筛选器
  • 由行上下文转换而来的筛选器
<think>我们面对的是一个DAX问题:在Power BI中,如何对两个筛选后的数值进除法运算。 根据用户的问题,我们需要计算两个筛选后的值的商。在DAX中,这通常涉及到先分别计算两个筛选条件下的值,然后进除法运算。 步骤: 1. 理解需求:用户想要对两个不同的筛选条件下的数值进除法运算。例如,计算某个产品在特定条件下的销售额与另一个条件下的销售额的比值。 2. 方法:我们可以使用DAX中的CALCULATE函数来改变筛选上下文,分别计算两个值,然后用除法运算符将它们相除。 示例: 假设我们有一个销售表,包含销售额(SalesAmount)和产品类别(ProductCategory)等字段。 需求:计算产品类别为“电子产品”的销售额与产品类别为“家具”的销售额的比值。 我们可以这样写: ``` Ratio = DIVIDE( CALCULATE(SUM(Sales[SalesAmount]), Sales[ProductCategory] = "电子产品"), CALCULATE(SUM(Sales[SalesAmount]), Sales[ProductCategory] = "家具") ) ``` 但是,这里需要注意的是,CALCULATE函数中的条件会覆盖外部上下文中的筛选。如果我们需要在同一个报表中同时保留两个不同的筛选条件,那么上述写法可能会因为上下文的不同而产生错误。 另一种更安全的方法是将两个计算分别定义为度量值,然后相除: ``` 电子产品销售额 = CALCULATE(SUM(Sales[SalesAmount]), Sales[ProductCategory] = "电子产品") 家具销售额 = CALCULATE(SUM(Sales[SalesAmount]), Sales[ProductCategory] = "家具") 比例 = DIVIDE([电子产品销售额], [家具销售额]) ``` 使用DIVIDE函数的好处是它可以自动处理分母为零的情况(返回空值或指定的替代值)。 如果用户希望在一个动态的筛选上下文中进这种计算(比如根据切片器选择的不同条件),那么可能需要使用更高级的技术,比如使用ALLSELECTED函数来保留部分筛选,或者使用变量来分别计算两个值。 例如,在同一个报表中,我们可能希望根据年份来动态计算比例,那么可以这样写: ``` 动态比例 = VAR Electronics = CALCULATE(SUM(Sales[SalesAmount]), Sales[ProductCategory] = "电子产品") VAR Furniture = CALCULATE(SUM(Sales[SalesAmount]), Sales[ProductCategory] = "家具") RETURN DIVIDE(Electronics, Furniture) ``` 但是,这样写的话,两个CALCULATE都会受到外部上下文(如年份切片器)的影响。也就是说,它会计算当前所选年份的电子产品销售额和家具销售额,然后相除。 如果用户的需求是固定的两个条件,那么上述方法即可。如果条件不固定,可能需要通过参数表或者更复杂的DAX来动态改变条件。 根据引用[4]中提到的FILTER函数,我们也可以使用FILTER来创建复杂的筛选条件,但通常CALCULATE加上简单的布尔表达式更高效。 总结:在Power BI中使用DAX对两个筛选后的数值进除法运算,核心是使用CALCULATE函数来应用筛选条件,然后使用除法运算符或DIVIDE函数进除法运算。 注意:在编写DAX时,要注意上下文的影响。建议将两个计算分别定义为度量值,然后再相除,这样在报表中使用时更加灵活,也便于调试。 下面我们给出一个更通用的示例,假设用户需要根据不同的筛选条件(可能是动态的)来计算两个值的商。 例如,用户可能有两个不同的筛选条件,分别来自两个不同的切片器(比如一个选择地区,一个选择产品类型),然后计算这两个条件下的销售额的比值。 这时,我们可以这样: ``` 条件1销售额 = CALCULATE(SUM(Sales[SalesAmount]), Condition1_Fields = SelectedValue1, ...) 条件2销售额 = CALCULATE(SUM(Sales[SalesAmount]), Condition2_Fields = SelectedValue2, ...) 比例 = DIVIDE([条件1销售额], [条件2销售额]) ``` 但是,如果两个条件在同一张表的同一列上,那么同时应用两个条件可能会冲突。因此,我们需要确保两个条件不会冲突,或者分别在不同的列上。 如果用户需要在一个度量值中动态地指定两个条件,那么可能需要使用更高级的方法,比如使用表函数和变量。 由于用户的问题比较宽泛,我们给出一个基础而通用的解决方案。 因此,我们建议用户按照以下步骤操作: 1. 分别创建两个度量值,用于计算在各自筛选条件下的结果。 2. 再创建一个度量值,将前两个度量值相除。 这样,在报表中,用户就可以自由地使用其他切片器,而这两个度量值会响应外部上下文,然后相除得到比例。 示例代码: ``` // 度量值1: 条件A的销售额 Sales_A = CALCULATE(SUM('Sales'[Amount]), 'Sales'[Category] = "A") // 度量值2: 条件B的销售额 Sales_B = CALCULATE(SUM('Sales'[Amount]), 'Sales'[Category] = "B") // 度量值3: 比例 Ratio_A_B = DIVIDE([Sales_A], [Sales_B]) ``` 在报表中,如果用户添加了年份切片器,那么Ratio_A_B将自动计算当前所选年份下,类别A与类别B的销售额比例。 如果用户希望条件A和条件B不受外部上下文的影响(例如,总是计算整个数据集的类别A和类别B),那么可以在CALCULATE中使用ALL函数来移除筛选。 例如: ``` Sales_A_Total = CALCULATE(SUM('Sales'[Amount]), 'Sales'[Category] = "A", ALL('Sales')) ``` 但通常,我们会希望响应外部上下文(如年份、地区等),所以一般不使用ALL。 最后,如果用户的需求是更复杂的动态条件,可能需要使用参数表或者SWITCH函数来动态切换条件。 由于用户问题中没有详细说明筛选条件是否是动态变化的,我们给出最常用的方法。 因此,回答如下:</think>在 Power BI 中使用 DAX 对两个筛选后的数值进除法运算,核心是通过 `CALCULATE` 函数结合筛选器动态计算分子和分母,再用 `DIVIDE` 函数处理除法。以下是具体实现方法: --- ### 解决方案(分步说明) #### 1. **基础语法结构** ```dax 结果 = DIVIDE( CALCULATE( [分子表达式], 分子筛选条件 ), CALCULATE( [分母表达式], 分母筛选条件 ), [可选:分母为零时的返回值] // 默认为空值 ) ``` #### 2. **实际应用示例** 假设需要计算 **华东地区销售额** 与 **所有地区销售额** 的比值: ```dax 销售占比 = DIVIDE( CALCULATE( SUM('销售表'[销售额]), '销售表'[地区] = "华东" ), // 分子:华东地区销售额 CALCULATE( SUM('销售表'[销售额]), ALL('销售表'[地区]) ), // 分母:所有地区销售额(用ALL移除地区筛选) 0 // 分母为零时返回0 ) ``` #### 3. **动态筛选场景** 若需基于切片器动态计算(如:**A产品销量** / **B产品销量**): ```dax 动态比值 = VAR 分子值 = CALCULATE( SUM('订单表'[销量]), TREATAS( {"A产品"}, '产品表'[品名] ) ) // 筛选A产品 VAR 分母值 = CALCULATE( SUM('订单表'[销量]), TREATAS( {"B产品"}, '产品表'[品名] ) ) // 筛选B产品 RETURN DIVIDE( 分子值, 分母值 ) ``` #### 4. **处理复杂筛选** 当筛选条件涉及多列时,用 `FILTER` 函数: ```dax 特殊场景比值 = DIVIDE( CALCULATE( [销售额], FILTER( '表', '表'[类别] = "X" && YEAR('表'[日期]) = 2023 ) ), CALCULATE( [销售额], FILTER( '表', '表'[类别] = "Y" ) ), BLANK() ) ``` --- ### 关键点说明 1. **`CALCULATE` 的核心作用** - 修改筛选上下文,实现动态计算[^2][^4]。 - 可嵌套 `FILTER`、`ALL`、`TREATAS` 等函数精确控制筛选范围。 2. **`DIVIDE` 的优势** - 自动处理分母为零的错误(优于直接使用 `/` 运算符)[^4]。 - 语法:`DIVIDE(分子, 分母, [错误返回值])`。 3. **筛选器类型选择** - 静态筛选:直接写条件(如 `'表'[列] = "值"`) - 动态筛选:用 `TREATAS` 或 `VALUES` 响应切片器[^4] - 去筛选:用 `ALL` 忽略特定列筛选[^4] --- ### 验证示例 | 场景 | DAX 公式片段 | |-----------------------|--------------------------------------------------| | 计算华东区销售占比 | `CALCULATE(SUM(Sales), Region="East") / CALCULATE(SUM(Sales), ALL(Region))` | | 响应切片器的产品比值 | `DIVIDE( CALCULATE(SUM(Qty), Product="A"), CALCULATE(SUM(Qty), Product="B") )` | > 提示:在报表中直接拖入该度量值,结果将随用户交互(如切片器、图表点击)动态更新[^2][^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PowerBI | 夕枫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值