DAX 中有许多可以用于检查上下文中的筛选器及其效果的函数,利用它们既可以帮助我们检查度量值的计值环境,有时也可以辅助我们进行层次判断,以选择不同的计值逻辑。
例如对于许多财务类指标都会涉及合并抵消,因此视所在层级要选择不同的数据来源或计算方法。再譬如在进行排序时想分别按所在层级排序等。
本文将使用以下两个表格作为示例来观察各个函数的应用效果
ISFILTERED和ISCROSSFILTERED
ISFILTERED(列)可以判断在当前计值区域中,是否有直接作用于该列的筛选器,并返回TRUE/FALSE值。该函数也可以接受表作为参数,使用表时则判断表中是否有任意一列受到了直接筛选。
而ISCROSSFILTERED(列)则判断在当前计值区域中,是否有直接或经过传导的筛选器作用于该列。同理,使用表作为参数时,判断表中是否有任意一列受到筛选。
直接筛选:来自切片器、筛选器、视觉对象中的行或列的筛选
传导筛选:经过表上的其它列、或者关系模型传导而来的筛选
接下来,创建一组度量值:
ISFILTERED表 = ISFILTERED('表1') ISFILTERED一级 = ISFILTERED('表1'[一级]) ISFILTERED二级 = ISFILTERED('表1'[二级]) ISCROSSFILTERED一级 = ISCROSSFILTERED('表1'[一级]) ISCROSSFILTERED二级 = ISCROSSFILTERED('表1'[二级])
然后我们创建一个多行卡和一个矩阵(矩阵的行来自表1的一级和二级),分别将这些度量值放入,得到如下结果:
接下来我们先识别一下视觉对象中各计值区域的上下文,再对照函数的功能,就能理解为什么会有这样的结果。
首先看isfiltered相关:
- 对表格中的一级汇总,例如第一行① ,其上下文是: ‘表1’[一级]=“A” ,只有字段[一级]上有直接筛选,所以[ISFILTERED一级]=TRUE,而[ISFILTERED二级]=FALSE,而由于已经有一个字段受到筛选了,所以[ISFILTERED表]也返回了TRUE。
- 而对二级汇总,例如第二行② ,其上下文是:‘表1’[一级]=“A” &&‘表1’[二级]=“a1” ,两个字段上均有直接筛选,所以三个isfiltered相关的度量值都是TRUE;
- 对总计③,以及上方的多行卡,由于是整表的全部数据都参与了计值,所以在两个字段上都是没有筛选的,因此三个度量值都返回了FALSE。
再看iscrossfiltered相关:
- 对区域①,虽然字段[二级]没有受到直接的筛选,但由‘表1’[一级]=“A”已经传递了一层筛选过来,所以[ISCROSSFILTERED二级]返回了TRUE。
- 其余存在直接筛选的区域都直接得到了TRUE。
接下来我们点击矩阵中的任意一行,可以看到由于默认交互的存在,该行的筛选上下文也作用到了多行卡上,因此卡片中的各项度量值都变成了TRUE。与此同时矩阵中总计行还都是FALSE。
接下来我们再将矩阵复原,直接添加一个切片器,如下图所示:
该切片器形成了对[一级]列的筛选,可以看到这个来自矩阵外部的筛选,让不但多行卡、连同矩阵“总计”行的度量值都发生了变化。
接下来,我们为表1和表2的字段[一级]创建一个连接关系:
将'表2'[中文]字段放入切片器,并添加筛选:
可以看到,由该表通过连接关系传递来的筛选关系,使多行卡中的两个iscrossfiltered的度量值都变为了TRUE,但isfiltered相关的度量值由于只检测直接筛选,因此不受影响。
综上,我们可以基本了解了交叉筛选与直接筛选的区别以及这两个函数的作用,也观察了在不同的交互场景下对它们的影响。在使用它们来进行辅助判断时,切记要考虑最终的应用方式,以确保达到预期的效果。
HASONEFILTER
hasonefilter判断当前列在直接筛选器作用下是否只筛出了一个非重复值。例如创建以下度量值:
HASONEFILTER一级 = HASONEFILTER('表1'[一级]) HASONEFILTER二级 = HASONEFILTER('表1'[二级])
可以看出,矩阵中的每一行的字段[一级]的筛选结果都是单独的值,所以对度量值[HASONEFILTER一级]都返回TRUE,对字段[二级]的明细行也是如此。而两个度量值在总计行,都没有直接筛选,所以都得到FALSE。
但当我们将字段[二级]放入切片器并加上筛选后,可以看到:
此时在一级汇总行以及总计行中,该字段都受到了直接筛选器的影响,且筛选值只有一个(b1),因此[HASONEFILTER二级]返回了TRUE。
可以看到,当切片器传入多选时,该度量值又变回了FALSE。
HASONEVALUE
hasonevalue判断该列在当前筛选上下文中是否只有一个非重复值,它与前述的hasonefilter之间的区别就在于,前者只判断直接筛选器的作用。如下图所示,可以看到在同样位置,[hasonevalue二级]返回了TRUE,虽然此处没有对[二级]字段做直接筛选,但因为在C类下级只有c1一个值,满足函数的判断条件,所以得到了不同的结果。
HASONEVALUE一级 = HASONEVALUE('表1'[一级]) HASONEVALUE二级 = HASONEVALUE('表1'[二级])
之前我们在介绍rankx时曾经使用hasonevalue来辅助判断,使总计行不参与排序。在许多参考文章中也经常会看到使用hasonevalue来辅助进行层次判断的案例,在学过本例后就会知道,在次级分类只有一个值时需要慎重使用。
ISINSCOPE
isinscope判断该列是否存在筛选,且正处于层次结构(如行或列标签)中。例如:
ISINSCOPE一级 = ISINSCOPE('表1'[一级]) ISINSCOPE二级 = ISINSCOPE('表1'[二级])
如下图所示,在没有其它筛选影响时,ISINSCOPE的表现与ISFILTERED完全一致。
但当我们使用切片器对这两个字段添加了筛选后,可以看到总计行的ISFILTERED度量值都变为了TRUE,因为它们受到了筛选。而ISINSCOPE仍然返回FALSE,因为函数还判断了当前位置,而总计并不属于层次结构。
由此我们可以发现,ISINSCOPE在层次判断方面表现得最为准确。而我们日常使用时,根据要使用的对象、以及需要的交互效果,选择最适宜的函数即可。