PowerBI/DAX之理解ALLEXCEPT函数

本篇文章将介绍ALLEXCEPT函数的使用,ALLEXCEPT函数的使用频率没有ALL函数高,但在某些情况下却是很有用的。当我们需要移除多个筛选器并保留少数筛选器时,使用ALLEXCEPT函数能够大大减少代码的书写量。


ALLEXCEPT函数的语法结构

语法:

ALLEXCEPT ( <TableName>, <ColumnName>, [ <ColumnName>, [ … ] ] )

作用:

ALLEXCEPT函数也有两种用法,一种是用作表函数,另一种则是用作筛选调节器。ALLEXCEPT函数的具体作用如下:

1、若ALLEXCEPT用作表函数时,将忽略任何筛选器,返回第一参数的表的扩展表中除所指定的列之外的所有列的现有值的唯一值组合,但扩展表上的列不可见。

2、若ALLEXCEPT用作筛选调节器时,将移除第一参数指定的表的扩展表中除所指定列之外的其余列上的所有筛选器。

ALLEXCEPT函数的第一参数必须为基础表,第二参数可以是一个或多个列,这些列必须来自第一参数所指定的基础表的扩展表上的列。此外第二参数还有个隐藏用法,就是直接使用基础表,等价于把该基础表转换成其扩展表上存在的多个列。


本篇文章使用到的数据与数据模型如下图所示:


将ALLEXCEPT函数用作表函数

若ALLEXCEPT用作表函数时,将忽略任何筛选器,返回第一参数的表的扩展表中除所指定的列之外的所有列的现有值的唯一值组合,但扩展表上的列不可见。

为了更好地理解这句话,下面用一个简单的例子来描述:假设有某个表具有四列,列名分别为:A、B、C、D,那么当ALLEXCEPT函数的第二参数指定了A列,那么将把BCD三列完整提取出来形成一个表,然后再对这个表按行为单位进行去重,然后ALLEXCEPT函数返回这个表去重后的结果。

其实上面的这个简单例子可以用ALL函数等价表示出来,即:

// 该等价写法只在ALLEXCEPT函数用作表函数时等价

ALLEXCEPT('TableName','TableName'[ColumnName1])

----------------假设表只有四列,那么ALLEXCEPT等价于---------------

ALL('TableName'[ColumnName2],'TableName'[ColumnName3],'TableName'[ColumnName4])

注意:上面这个等价的写法其实并不等价,只是为了方便大家理解ALLEXCEPT函数的行为才给出的,实际上还需要考虑扩展表,而且返回结果中的扩展表上的列是不可见的。

下面来看一些帮助理解的例子,为了方便起见,使用查询来进行演示:

在上面这个例子中,虽然有一个内部筛选器,但是ALLEXCEPT在作为表函数时是会忽略任何筛选器的,因此该内部筛选器可以当作不存在。然后,ALLEXCEPT返回订单表的扩展表上除了'订单表'[产品名称]外的其他列去重后的结果,但其中属于扩展表上的列不可见,因此最终返回的可见部分就只有订单表上除产品名称外的其他三个列。该例子中ALLEXCEPT的行为如下图所示:

由于ALLEXCEPT的第二参数可以是来自第一参数的基础表的扩展表上的列,因此在使用ALLEXCEPT时需要时刻注意要以扩展表的视角来看待其行为,比如下面这个例子:

在这个例子中,ALLEXCEPT的第二参数使用了订单表的扩展表上的字段,返回的是整个订单表去重后的结果,它的计值行为如下图所示:

通过上面这两个例子,相信都能理解ALLEXCEPT在用作表函数时的行为,但这两个例子可能没体现出扩展表的影响,因为在返回结果中扩展表上的其他列是不可见的。为了更好的理解为何要以扩展表的视角来理解ALLEXCEPT函数,下面再来看一个例子:

由于ALLEXCEPT返回的表是包含扩展表上的列的,因此可以基于扩展表上的列的筛选器来实现逆向筛选,从而观察到ALLEXCEPT对扩展表的影响。在上面这个例子中,ALLEXCEPT返回的结果与行为如下图所示:

然后FILTER过滤ALLEXCEPT的返回结果,只保留A产品的数据。

然后将过滤后的数据作为CALCULATETABLE的筛选器参数,此时,订单表的四个列以及产品表的产品类别列都会被设置筛选器,然后由于筛选器无法逆向筛选,或者说产品表的扩展表不包含订单表的任何列,因此来自订单表的那四个筛选器都无法筛选产品表,只有来自产品表的产品类别筛选器能够筛选到产品表,因此最终产品表返回类别1的数据。

虽然ALLEXCEPT返回的表中看不到扩展表上的列,但是通过上面这个例子也可以间接观察到ALLEXCEP的行为是以第一参数的扩展表为目标来操作的,所以在使用ALLEXCEPT时需要时刻注意要以扩展表的视角来理解。

此外,ALLEXCEPT的第二参数是可以指定多个列的,比如:

但是不能把第一参数的表的所有字段都排除掉,至少需要保留一列,否则将会报错,如下图所示:

以上就是ALLEXCEPT在用作表函数时的行为了,只要注意以扩展表的视角来理解,并记住会忽略任何筛选器就可以了。


将ALLEXCEPT函数用作筛选调节器

当ALLEXCEPT函数用作筛选调节器时,将移除第一参数指定的表的扩展表中除所指定列之外的其余列上的所有筛选器。

ALLEXCEPT在作为筛选调节器时,其行为不再是返回表,而是与ALL一样,是移除现有的筛选器,只不过ALLEXCEPT属于批量移除,移除的范围为:第一参数指定的表的扩展表上除了第二参数指定的列之外的其他列上的筛选器。

下面通过一个简单的例子来辅助理解ALLEXCEPT作为筛选调节器时的行为,如下图所示:

在这个例子中,外层CALCULATETABLE中定义了三个不同的筛选器,然后使用ALLEXCEPT来移除筛选器,移除的范围为:订单表的扩展表上除了产品表的产品类别外的其他列上的筛选器。因此最终只有产品表的产品类别筛选器能保留下来,其他两个筛选器都被移除了,所以最终返回类别1的订单表数据。

ALLEXCEPT移除的筛选器范围如下图所示:

ALLEXCEPT用作筛选调节器时的行为比较简单,而且应该也比较好理解,只要搞清楚会被移除的筛选器范围就可以了。


ALLEXCEPT第二参数的隐藏用法

前面提到过,ALLEXCEPT的第二参数还有个隐藏用法,就是直接使用基础表,其等价于把该基础表转换成其扩展表上存在的多个列。如下所示:

//假设Table_B只有四列,且Table_B是Table_A的上级表

ALLEXCEPT('Table_A','Table_B'[Column1],'Table_B'[Column2],'Table_B'[Column3],'Table_B'[Column4])

等价于:

ALLEXCEPT('Table_A','Table_B')

在第二参数中使用表时,只能指定第一参数的表的上级表,而且不能与第一参数的表相同。

此外,该隐藏用法只是在语法层面上的,不会影响ALLEXCEPT的行为,相当于一个语法糖,具体行为还要看是用作表函数还是用作筛选调节器,可结合上面给出的等价写法进行理解。


总结

ALLEXCEPT函数与ALL函数类似,都是既可以用作表函数又可以用作筛选调节器,但功能强大的同时也带来了更多的复杂性,因此需要多多练习与总结。

<think>好的,我现在需要回答用户的问题:“在powerbi DAX函数中筛选器的区别”。首先,我需要回忆DAX中常见的筛选器函数,比如FILTER、ALL、ALLEXCEPT、ALlSELECTED、USERELATIONSHIP、CROSSFILTER等,以及它们的作用和区别。用户可能想了解这些函数在应用筛选时的不同行为,比如是否移除上下文、影响哪些表或列、如何修改关系方向等。 首先,我需要明确DAX中的筛选器函数主要用于控制数据上下文,影响计算结果。常见的筛选器函数可以分为几类:移除筛选的函数(如ALL、ALLEXCEPT)、应用筛选的函数(如FILTER)、处理上下文的函数(如ALlSELECTED)、以及管理关系的函数(如USERELATIONSHIP、CROSSFILTER)。 接下来,我需要逐一解释这些函数的作用、语法和使用场景,并对比它们的区别。例如,ALL函数会移除指定表或列的所有筛选,而ALLEXCEPT则保留指定列的筛选,移除其他列的筛选。FILTER函数则是在现有上下文中应用新的筛选条件,返回符合条件的行。ALlSELECTED通常用于处理用户交互中的筛选,考虑所有选中的筛选器,包括页面、切片器等。USERELATIONSHIP和CROSSFILTER则用于临时更改关系的激活状态或方向。 需要注意用户可能混淆的点,比如ALL和ALLEXCEPT的区别,FILTER与CALCULATE中筛选参数的关系,以及ALlSELECTED在视觉对象上下文中的行为。此外,还要举例说明不同函数的使用场景,帮助用户理解何时选择哪个函数。 最后,确保回答结构清晰,先总述筛选器函数的作用,再分类型详细解释每个函数的区别,最后总结应用场景。同时,按照用户要求,在回答末尾生成3-5个相关问题。 </think>在 Power BIDAX 函数中,**筛选器函数**主要用于控制数据上下文(行上下文或筛选上下文),影响计算结果的范围。不同筛选器函数的核心区别在于 **对现有筛选的处理方式**(如移除、保留、修改)、**作用对象**(表、列、关系)以及 **应用场景**(计算、上下文转换等)。以下是常见筛选器函数的详细对比: ### **一、移除筛选的函数:ALL、ALLEXCEPT、ALLSELECTED** 这类函数用于清除或限制现有筛选上下文的影响,常用于计算“总计”或“不受部分筛选影响”的值。 | 函数 | 核心作用 | 关键区别 | 典型场景 | |--------------------|--------------------------------------------------------------------------|--------------------------------------------------------------------------|--------------------------------------------------------------------------| | `ALL(<表或列>)` | 移除指定表或列的**所有筛选**(包括行上下文和筛选上下文)。若不指定参数,移除整个表的筛选。 | 完全清除筛选,仅保留原始数据(无任何筛选条件)。 | 计算“全局总计”(如“所有地区的总销售额”,忽略切片器对地区的筛选)。 | | `ALLEXCEPT(<表>, <列1>, <列2>, ...)` | 移除表中**除指定列外**的所有筛选(仅保留指定列的筛选)。 | 选择性保留部分列的筛选,其他列的筛选被清除。 | 计算“按特定维度分组的总计”(如“保留地区筛选,但清除产品类别的筛选”)。 | | `ALLSELECTED(<表或列>)` | 移除**用户交互外的筛选**(保留页面/视觉对象中用户主动选择的筛选,如切片器、交叉筛选)。 | 仅清除“隐式筛选”(如计算列或行上下文的筛选),保留用户显式交互的筛选。 | 计算“与用户交互一致的总计”(如“当前选中的产品类别下,所有地区的总销售额”)。| #### **示例对比** 假设表 `Sales` 包含 `地区`、`产品类别`、`销售额` 列,且页面切片器筛选了“地区=华北”: - `ALL(Sales)`:忽略“地区=华北”的筛选,计算所有地区的总销售额。 - `ALLEXCEPT(Sales, 产品类别)`:保留“产品类别”的筛选(若有),但清除“地区”的筛选(包括切片器的“华北”筛选),计算各产品类别在所有地区的总销售额。 - `ALLSELECTED(Sales)`:保留切片器“地区=华北”的筛选(用户显式选择),计算华北地区的总销售额(若其他隐式筛选存在则清除)。 ### **二、应用筛选的函数:FILTER** `FILTER(<表>, <逻辑表达式>)` 用于在现有上下文中**应用新的筛选条件**,返回符合条件的行组成的表。与直接在 `CALCULATE` 中使用筛选参数不同,`FILTER` 通常作为参数传递给其他函数(如 `SUMX`、`CALCULATE`)。 #### **核心区别** - **与 `CALCULATE` 直接筛选的对比**:`CALCULATE` 会直接修改筛选上下文(覆盖或添加筛选),而 `FILTER` 仅返回一个子集表,需结合迭代器(如 `SUMX`)或 `CALCULATE` 使用。 - **行上下文与筛选上下文**:`FILTER` 内部使用行上下文(逐行判断逻辑表达式),而 `CALCULATE` 直接操作筛选上下文(列级别的筛选)。 #### **示例** 计算“产品类别=电子”且“销售额>1000”的订单数量: ```dax 电子高销售额订单数 = COUNTROWS( FILTER( Sales, Sales[产品类别] = "电子" && Sales[销售额] > 1000 ) ) ``` ### **三、管理关系的筛选器:USERELATIONSHIP、CROSSFILTER** 这类函数用于临时修改模型中的关系(如激活非活动关系、调整筛选方向),仅在 `CALCULATE` 或 `CALCULATETABLE` 中生效。 | 函数 | 核心作用 | 关键区别 | 典型场景 | |---------------------------|--------------------------------------------------------------------------|--------------------------------------------------------------------------|--------------------------------------------------------------------------| | `USERELATIONSHIP(<列1>, <列2>)` | 强制使用指定的列对建立关系(即使模型中该关系未激活)。 | 仅激活一对列之间的关系,其他关系保持原样。 | 当模型中存在多对关系(如同一对表有多个关联列),需指定使用某一特定关系。 | | `CROSSFILTER(<列1>, <列2>, <方向>)` | 修改指定关系的筛选方向(单向/双向/无)。 | 动态调整关系方向(默认单向:从一方到多方)。 | 解决双向筛选导致的循环依赖(如两个维度表互相影响),或临时启用双向筛选。 | #### **示例** 假设模型中 `订单表` 与 `日期表` 有两个关系(`订单日期` 和 `发货日期`),默认激活 `订单日期`,但需按 `发货日期` 筛选: ```dax 发货日期销售额 = CALCULATE( SUM(订单表[销售额]), USERELATIONSHIP(订单表[发货日期], 日期表[日期]) ) ``` ### **总结:如何选择筛选器函数?** - 若需**清除筛选**:用 `ALL`(完全清除)、`ALLEXCEPT`(保留部分列)、`ALLSELECTED`(保留用户交互筛选)。 - 若需**应用新筛选**:用 `FILTER`(结合迭代器或 `CALCULATE`)。 - 若需**管理关系**:用 `USERELATIONSHIP`(激活非活动关系)、`CROSSFILTER`(调整筛选方向)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

PowerBI | 夕枫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值