6、DAX的ALL类函数详解以及影子筛选上下文的介绍—上篇

7 篇文章 9 订阅


一、前言

  在我写下这段前言的时候,我的内心非常的复杂,我在想要不要把ALL类函数讲得这么详细,我很想只简单介绍一个ALL的用法就完事了。但是ALL类函数在DAX里的重要性可以说是占据了半壁江山,不好好地讲解清楚可能会让读者不明所以,从而有可能走了弯路,这就有违我的初衷了。但是详细讲解的话,我又担心自己对语言的驾驭能力不足,不能将我的理解全部讲解清楚,因为ALL类函数中的ALLSELECTED涉及到了影子筛选上下文,可以说是DAX中最复杂的函数了。复杂到什么程度呢?复杂到你在网上搜索影子筛选上下文这个关键字都搜索不到相关的学习资料,可以说,在网上关于DAX的学习资料里基本没有关于影子筛选上下文的文章,如果你不信可以自行去搜索。我也阅读过许多关于DAX的学习资料,但我只在DAX圣经里看到过影子筛选上下文,网上关于影子筛选上下文的学习资料的稀缺也是让我下定决心详细介绍ALL类函数的原因,希望能够填补这份空缺吧。

  可能有人看了上面这段话后会觉得影子筛选上下文非常重要,但其实它并没有你想象中的那么重要,因为能激活影子筛选上下文的函数只有ALLSELECTED。所以,若你不深层次的使用ALLSELECTED那么完全可以忽略影子筛选上下文,而且我也不建议你使用ALLSELECTED来激活影子筛选上下文,完全可以使用更好理解的VAR和RETURN来代替,这也是网上关于影子筛选上下文的资料过少的原因,毕竟谁也不想花大力气去学习一个复杂但却不能派上用场的东西。因此,影子筛选上下文只适合那些想要深究ALLSELECTED原理的人,而并不太适合追求实际应用的人。

  在本篇文章中将讲解除ALLSELECTED外的ALL类函数的用法,ALLSELECTED将在下篇文章中讲解。废话不多说了,下面开始正式介绍ALL的家族成员。

二、ALL的用法

  ALL类函数之所以重要,主要是因为ALL类函数能够忽略筛选器或者移除筛选器,因此能使用ALL类函数来扩张计值环境,从而实现各种业务逻辑。ALL的语法结构如下:

  • 语法:
ALL ( <TableName> | <ColumnName> , [ <ColumnName>, [ <ColumnName>, [ … ] ] ] )
  • 作用:

  ALL类函数通常有两种用法,一种是作为表函数,另一种则是作为筛选调节器,ALL的作用具体如下:

  1、若将ALL用作表函数时,ALL返回参数所指定的表中的所有行或列中的所有不重复值,忽略任何筛选器;

  2、若将ALL用作筛选调节器时,将移除参数所指定的表的扩展表或指定的列上的所有筛选器。


  可能有人会看不懂ALL的语法结构,因此先对ALL能接受的参数做一个简单说明。简单来讲,ALL的参数要么直接是表,要么就是列。若其参数为表,例如:ALL('TableName'),那么这个表只能是基础表而不能是返回表的表函数。若其参数为列,那么可以使用单列或多列,例如:ALL('TableName'[ColumnName1],'TableName'[ColumnName2]),当使用多列时,这些列必须来自同一张表。

2.1 将ALL用作表函数

  首先来看下将ALL用作表函数的情况,当ALL被用作表函数时,其作用以及行为都与VALUES非常相像,都是将其参数在数据模型中的可见值以表的形式返回,参数可以是列,也可以是表。但ALL与VALUES还是有所不同的,具体如下:

  1、若参数为列时,ALL将忽略任何对其参数起作用的筛选器,返回一列或多列的所有不重复值,所谓的重复值是以行为单位的;

  2、若参数为表时,ALL将忽略任何对其参数起作用的筛选器,返回该表的所有行。其中,作为参数的表只能是基础表,不能是返回表的表达式;

  3、若遇到由参照完整性不匹配而产生的空行,ALL的行为与VALUES的行为一致,即:ALL会返回由参照完整性不匹配而产生的空行。

  下面来看一些帮助理解的例子:

  1、参数为表时,ALL会返回表的所有行,如下图所示:

在这里插入图片描述
  2、参数为单列时,ALL会返回列的所有不重复值,如下图所示:

在这里插入图片描述
  3、参数为多列时,ALL会返回多列的现有值的唯一值组合,并不是返回多列的笛卡尔积,如下图所示:

在这里插入图片描述
  4、ALL会返回由参照完整性不匹配而产生的空行,如下图所示:
在这里插入图片描述
  这里用到的度量值公式如下:

商品表的行数:=COUNTROWS('商品表')

ALL_商品表的行数:=COUNTROWS(ALL('商品表'))

values_商品编码:=COUNTROWS(VALUES('商品表'[商品编码]))

ALL_商品编码:=COUNTROWS(ALL('商品表'[商品编码]))

values_售价:=COUNTROWS(VALUES('商品表'[售价]))

ALL_售价:=COUNTROWS(ALL('商品表'[售价]))

  如果你对ALL处理由参照完整性不匹配而产生的空行的行为不理解的话,可以看我的上篇文章:5、DAX的常用表函数之VALUES与DISTINCT,上面的例子用的数据也是上篇文章的,而我在上篇文章里已经详细讲解过了,这里就不再重复讲解,因为ALL处理由参照完整性不匹配而产生的空行的行为与VALUES一致。

  5、由于ALL的参数可以引用多列,因此有人可能会采用引用多列的方式来返回表的所有行,这是错误用法,这里举个小例子来说明,用到的度量值公式如下:

ALL_TABLE := COUNTROWS( ALL( '门店' ) )

ALL_COLUMNS := COUNTROWS( ALL( '门店'[店号],'门店'[店名] ) )

VALUES_TABLE := COUNTROWS( VALUES( '门店' ) )

DISTINCT_TABLE := COUNTROWS( DISTINCT( '门店' ) )

  结果如下图:

在这里插入图片描述
  从上图中可以看到,想要通过ALL引用表的所有列来返回表的所有行的做法是错误的,这样的做法并不能返回表的所有行,即使你引用了表的所有列。原因就在于当ALL的参数为多列时,ALL会返回多列的现有值的唯一值组合。此外,我在这个例子中也加入了VALUES和DISTINCT的对比,如果对它们的结果不解的话,我还是建议你去看我的上一篇文章,这里不再重复讲解。

  帮助理解的例子就到这里结束,如果还不能理解的话可以亲自去实验,ALL用作表函数需要注意的地方上面都已经列出,根据实验结果归纳总结一下很容易就能掌握。很多人都不注重细节,但细节可以决定成败!

2.2 将ALL用作筛选调节器

2.2.1 筛选调节器的介绍

  ALL类函数大多都存在两种用法,一个是作为表函数,另一个则是用作筛选调节器。首先,CALCULATE和CALCULATETABLE的筛选器参数是可以有多个的,且这些筛选器参数能够接受布尔表达式和表筛选以及一些能够改变新筛选上下文的生成方式的函数,这些能够改变新筛选上下文的生成方式的函数就是筛选调节器。筛选调节器主要有这些函数:ALL、ALLEXCEPT、ALLSELECTED、ALLNOBLANKROW、ALLCROSSFILTERED、REMOVEFILTERS、KEEPFILTERS、CROSSFILTER、USERELATIONSHIP,可以看到,ALL类函数直接就占据了一半。

  要知道,ALL类函数除了用作筛选调节器外,还可以用作表函数,那么就必须要搞清楚什么时候用作表函数,又是什么时候用作筛选调节器。简单来说,直接把ALL类函数用在CALCULATE和CALCULATETABLE的筛选器参数上,那么此时的ALL类函数就是筛选调节器,除此之外的都是表函数。需要注意,如果ALL类函数在CALCULATE的筛选器参数上出现,但在ALL类函数的外面还套了函数,那么这样的ALL类函数是用作表函数而不是筛选调节器,请重点注意上面所描述的直接这个词的含义。

2.2.2 ALL用作筛选调节器时的行为

  搞清楚了ALL类函数什么时候用作筛选调节器,那么也是时候来看一下ALL用作筛选调节器时的行为是什么了。

  ALL在用作筛选调节器时,将移除参数所指定的表的扩展表或指定的列上的所有筛选器。ALL 从不添加筛选器,只移除参数列出现的所有筛选器。因为还没有讲解到扩展表,所以我简单介绍下:某个基础表的扩展表包含基础表的所有列以及可以通过一对多关系筛选基础表的所有表和列。具体的在以后的文章中会讲解,现在你可以把某个基础表的扩展表理解为:除了基础表自身的所有列外还隐藏着一些属于其他表的列。

  ALL在作为筛选调节器时,其参数也是可以接受表或者多列,具体如下:

  1、若参数为列时,ALL将移除其参数所指定的列上的筛选器,注意是仅移除指定列上的筛选器而不会移除交叉筛选的筛选器,而且不会返回任何值

  2、若参数为表时,ALL将移除其参数所指定的表的扩展表的所有列上的筛选器,不会返回任何值

  下面举了一些例子来帮助理解:

  1、先来看一个简单地移除筛选的例子,用到的度量值公式如下:

总销量 := CALCULATE(SUM('T3销售'[T3销售册数]))

增加筛选-总销量 := CALCULATE(CALCULATE(SUM('T3销售'[T3销售册数])),'T1子类'[T1子类K]="11机械")

移除筛选-总销量 := CALCULATE(CALCULATE(SUM('T3销售'[T3销售册数]),ALL('T1子类'[T1子类K])),'T1子类'[T1子类K]="11机械")

  结果如下图:

在这里插入图片描述
  可以看到,在[移除筛选-总销量]这个度量值里的ALL是直接用作了CALCULATE的筛选器参数,在ALL的外面并没有再套函数,所以ALL在这里被用作了筛选调节器,它的作用就是移除指定列上的筛选器。一般情况下,我建议只用ALL移除指定列上的筛选器,而不要直接移除整个表的筛选器,因为移除表的筛选器,其实还移除了这个表的扩展表上的筛选器,这有可能会带来一些意料之外的情况。所以,在你还不能彻底驾驭DAX前,最好只移除需要移除的筛选器。

  2、再来看一个比较复杂的例子,在这个例子中你将了解到只移除列上的筛选器与移除整个表的筛选器之间的区别,用到的计算列公式如下:

子类的销量 := CALCULATE(SUM('T3销售'[T3销售册数]))

所有子类的销量和 := CALCULATE(SUM('T3销售'[T3销售册数]),ALL('T1子类'))

对应大类的销量和 := CALCULATE(SUM('T3销售'[T3销售册数]),ALL('T1子类'[T1子类K],'T1子类'[T1大类]))

  为了避免循环依赖,每次只使用一个计算列,先来看下前两个计算列的结果,如下图:

在这里插入图片描述
  在这里,CALCULATE会使每一行的行上下文转换成筛选上下文,从而使得筛选关系沿着数据模型传播,最终筛选了销售表的记录。所以,子类的销量这个计算列的结果就是每个子类对应的销量总和。然后,对于所有子类的销量和这个计算列而言,行上下文先转换成筛选上下文,然后又被CALCULATE的筛选器参数ALL给清除了所有筛选,所以才返回了全部的销量和。

  下面来看一下对应大类的销售和这个计算列的结果,如下图:

在这里插入图片描述
  貌似奇怪的事情发生了,为了方便对比,先将上面用到的两个计算列公式复制过来:

所有子类的销量和 := CALCULATE(SUM('T3销售'[T3销售册数]),ALL('T1子类'))

对应大类的销量和 := CALCULATE(SUM('T3销售'[T3销售册数]),ALL('T1子类'[T1子类K],'T1子类'[T1大类]))

  上面用到的两个计算列公式乍一眼看过去好像没什么区别,仅仅是所有子类的销量和这个计算列里的ALL直接用了表作参数,而对应大类的销量和这个计算列里引用了表的所有列。按理来说,这两种写法都是为了清除’T1子类’表各列上的筛选,但是两个计算列的结果却大不一样。

  造成这个问题(当你掌握了理论后也不能说是问题)的原因,主要是因为移除表的筛选器时其实就是移除这个表的扩展表上各列的筛选器,也就是说你不仅仅移除了ALL参数所指定的那个表的列,你还移除了别的表或列上的筛选器。而通过引用多列的方式来清除某个表的筛选,其实就是只清除了那个表自身列上的筛选器,别的表或列上的筛选器仍然存在。

  此时你可能会回过头再去看上面这个例子,然后你就可能会疑惑:“ 不对啊,那个产品子类表不是只有两列么,行上下文转换成筛选上下文那也就只有两个筛选器啊,哪来的其他筛选器啊 ”,关于这个疑问的解释那就是:基础表还隐藏着其扩展表上的属于其他表的列,这些其他列一般情况下不能读取和看到,但是当其被用作筛选时就会发生作用。在上面的例子中,由于行上下文转换成筛选上下文,所以产品子类表的其他列由于被用作筛选,所以就产生了作用。简单点说,用作筛选的表都是扩展表,所以产品子类表发生行上下文转换后所得到的筛选器不仅仅只有两个,还包括了产品子类表的上级表的列,也就是产品大类表上的列。因此,上面例子中通过引用多列的方式来清除表的筛选器仅仅只是清除掉了产品子类表自身列上的筛选器,还有一个产品大类的筛选器没有被清除,最终使得两个计算列的结果不一致。

  由于上面的例子涉及到了扩展表,所以不懂扩展表理论的人可能会很难理解,而我对文字的驾驭水平还不够,可能讲解得有点混乱。因此,我建议你在学习了扩展表理论后再来理解。关于扩展表理论,我会在以后的文章中讲解。

  我举上面的这个例子并不是为了展示我的知识有多么丰富,而只是想让你明白:一般情况下,最好只用ALL移除你需要移除的筛选器,而不要直接移除整个表的筛选器,因为移除表的筛选器,其实还移除了这个表的扩展表上的筛选器,在你没有深入理解DAX的理论之前可能会带来一些意料之外的情况。

2.3 ALL用作筛选调节器与用作表函数的区别

  我知道,可能有很多人都不明白ALL用作筛选调节器时的行为,总是将ALL理解成返回表的表函数,即使我在上文中反复强调:ALL用作筛选调节器时的行为是移除参数所指定的表的扩展表或指定的列上的所有筛选器,并不会返回任何值。在大多数情况下,将本应用作筛选调节器的ALL理解成了返回表的表函数也是逻辑自洽的,因为CALCULATE和CALCULATETABLE的筛选器参数是可以接受表筛选的。但是当遇到某些情况时,仍然把用作筛选调节器的ALL理解成表函数,那么得到的结果将无法解释。

  为了能够清晰明确地观察到ALL用作筛选调节器时的行为是移除筛选器而不是返回表,我特地设计了一个例子来说明。由于这个例子涉及到了扩展表理论,不理解扩展表的人很可能会理解不了,但我会尽我最大的努力去讲解清楚。如果你不能理解这个例子,你只需要记住:“ALL用作筛选调节器时的行为是移除参数所指定的表的扩展表或指定的列上的所有筛选器,并不会返回任何值。”,因为这个例子是为了说明这句话而设计的,而不是为了别的。

  废话不多说,先来看下这个例子使用到的数据模型,如下图所示:

在这里插入图片描述
  然后,在这个例子中将用到的度量值公式如下:

产品大类表的行数_1 = CALCULATE(COUNTROWS('T0大类'))

产品大类表的行数_2 = CALCULATE(COUNTROWS('T0大类'),'T3销售')

产品大类表的行数_3 = CALCULATE(COUNTROWS('T0大类'),ALL('T3销售'))

产品大类表的行数_4 = CALCULATE(COUNTROWS('T0大类'),FILTER(ALL('T3销售'),1))

  最后,将上面这四个度量值拖放到数据透视表的值字段,将产品子类拖放到数据透视表的行字段,得到的结果如下图所示:
在这里插入图片描述
  对于第一个度量值,由于产品子类表是产品大类表的下级表,且筛选关系只能沿着数据模型中的关系箭头的指向传播,所以产品子类表上的筛选器无法筛选到产品大类表的数据,所以第一个度量值返回的是产品大类表的所有行数,而产品大类只有三个,所以结果全为3。

  对于第二个度量值,直接把销售记录表用作了CALCULATE的筛选器参数,由于CALCULATE的各个内部筛选器都是在外部计值环境下单独计值的,所以销售记录表已经被行标签,也就是产品子类上的筛选器筛选了一遍。虽然销售记录表是产品大类表的下级表,筛选关系无法逆向传播,但是用作筛选的表都是扩展表,而销售记录表的扩展表就包括了产品大类,因此能够对产品大类表进行筛选。因为销售记录表已经被产品子类筛选了一遍,所以第二个度量值返回的是各产品子类对应的产品大类的数量,又因为每个产品子类只能属于一个产品大类,所以第二个度量值在各个产品子类下的结果应该全部为1,在总计行上应该为3。但是,我在销售记录表上将属于第三个产品大类的销售记录都删除了,因此总计行上的结果才为2。与此同时,销售记录表被第三个产品大类下的所属产品子类筛选后的结果为空,从而使得CALCULATE的计算器参数所在的计值环境为空,最终导致其对应值为空。

  对于第三个度量值,ALL被用作了筛选调节器,将销售记录表的扩展表上的所有筛选器都移除了,并不会返回任何值,使得CALCULATE的计算器参数在整个产品大类表上计值,所以第三个度量值返回的是产品大类表的所有行数。但实际上,在这个例子中的外部计值环境只有关于产品子类的筛选器而且ALL被用作筛选调节器并不会返回任何值,因此就算不移除产品子类的筛选器,所得到的结果也不会变,这与第一个度量值的情况一致。但,如果将ALL理解成返回表的表函数,那么结果将大不一样,具体请看第四个度量值的解释。

  对于第四个度量值,为了明确地使ALL被用作表函数而不是筛选调节器,因此在ALL的外面套了个FILTER,且让FILTER的第二参数为1,即返回FILTER第一参数的表的所有行,也就是销售记录表的所有行,因为ALL用作表函数时会忽略任何对其参数起作用的筛选器。前面说过,销售记录表是产品大类表的下级表,筛选关系无法逆向传播,但是用作筛选的表都是扩展表,而销售记录表的扩展表就包括了产品大类与产品子类,因此能够对产品大类表进行筛选,并且CALCULATE在确定最后的计值环境时用销售记录表的扩展表上的产品子类覆盖了外部计值环境(数据透视表行标签)中关于产品子类的筛选,所以第四个度量值返回的结果是:在销售记录表里存在销售记录的产品大类的数量,因此结果全部为2。

  我已经尽量详细地进行讲解了,再详细就超出本文的主题了,如果你还是不能理解这个例子,你只需要记住这句话就可以了:ALL用作筛选调节器时的行为是移除参数所指定的表的扩展表或指定的列上的所有筛选器,并不会返回任何值

2.4 利用ALL求总计百分比

  一般情况下,求解某个指标在总计里的占比是很常见的,在学习了ALL之后,就可以利用ALL能忽略或移除筛选器的特点来求解。下面来看一个求解各个产品子类的销量占总销量的百分之几的例子,用到的度量值公式如下:

销量 = SUMX('T3销售','T3销售'[T3销售册数])

总销量 = SUMX(ALL('T3销售'),'T3销售'[T3销售册数])

销量占比 = DIVIDE([销量],SUMX(ALL('T3销售'),'T3销售'[T3销售册数]))

  其中,DIVIDE函数是安全除法,能接受三个参数,第一个参数是分子,第二个参数是分母,第三个参数是分母为零时的替代结果(省略默认为空)。下面来看下结果,如下图:
在这里插入图片描述
  得到的结果符合预期,但如果将[销量占比]这个度量值的公式修改成如下:

销量占比 = DIVIDE([销量],SUMX(ALL('T3销售'[T3销售册数]),'T3销售'[T3销售册数]))

  得到的结果将有所变化,如下图所示:
在这里插入图片描述
  可以看到,销量占比的计算结果完全是错误的,造成这个问题的原因,就是因为ALL用作表函数时的参数若为列时,ALL将忽略任何对其参数起作用的筛选器,返回一列或多列的所有不重复值,从而使得计算销量占比时的分母变小了,得到的结果自然就大了。

  为了避免这种逻辑没问题但因为函数特性而引起的错误,我建议你使用移除筛选的方式来计算各种指标的占比。例如,将[销量占比]这个度量值的公式修改成如下:

销量占比 = DIVIDE([销量],CALCULATE([销量],ALL('T1子类'[T1子类K])))

  结果如下图:
在这里插入图片描述

三、其它ALL类函数的用法

3.1 ALLEXCEPT

  当你需要使用ALL来移除同一个表的多个列上的筛选器时,可以使用ALLEXCEPT来减少代码书写量。ALLEXCEPT的语法结构和函数作用如下:

  • 语法:
ALLEXCEPT ( <TableName>, <ColumnName>, [ <ColumnName>, [ … ] ] )
  • 作用:

  ALLEXCEPT的参数最少为两个,一个是表,另一个是表上的列。它的作用具体如下:

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

  2、若ALLEXCEPT用作筛选调节器时,将移除第一参数指定的表的扩展表中已应用的任何筛选器,只保留指定列的筛选条件。

  单纯地看ALLEXCEPT的作用可能很难理解,但其实ALLEXCEPT是可以使用ALL来重写的,只要理解了ALL,那么肯定能理解ALLEXCEPT。ALLEXCEPT的等价写法如下:

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

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

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

  其实前面的描述还是有些不太准确,上文提到过,当ALL的参数是多列时,那么这些列必须来自同一张表,但是ALLEXCEPT所指定的列却可以是来自第一参数指定的表的扩展表。也就是说,可以在ALLEXCEPT里指定保留扩展表上的列的筛选器,当然这只是用作筛选调节器时的行为。当ALLEXCEPT用作表函数时,将列指定为扩展表上的列,那么将返回第一参数的表的所有行而并不包括扩展表上的列。可以参考下面的查询:

在这里插入图片描述

3.2 ALLNOBLANKROW

  ALLNOBLANKROW与ALL几乎是一样的,区别只在于ALLNOBLANKROW不会返回由参照完整性不匹配而产生的空行,其他地方都与ALL一致。ALLNOBLANKROW的语法结构与函数作用具体如下:

  • 语法:
ALLNOBLANKROW ( <TableName> | ColumnName> , [<ColumnName>, [ <ColumnName>, [ … ] ] ]  )
  • 作用:

  1、将ALLNOBLANKROW用作表函数时,将返回参数所指定的表中的所有行或列中的所有不重复值,忽略任何筛选器,但不会返回由参照完整性不匹配而产生的空行;

  2、将ALLNOBLANKROW用作筛选调节器时,将移除参数所指定的表的扩展表或指定的列上的所有筛选器,并增加一个只删除由参照完整性不匹配而产生的空行的筛选器。

  需要注意的是:ALLNOBLANKROW只删除或过滤由参照完整性不匹配而产生的空行,对于基础表里的空白数据是可以正常返回的。具体如下图所示:
在这里插入图片描述
  用到的度量值公式如下:

ALLNOBLANK_商品表:=COUNTROWS(ALLNOBLANKROW('商品表'))

ALL_商品表:=COUNTROWS(ALL('商品表'))

ALLNOBLANK_商品编码:=COUNTROWS(ALLNOBLANKROW('商品表'[商品编码]))

ALL_商品编码:=COUNTROWS(ALL('商品表'[商品编码]))

ALLNOBLANK_售价:=COUNTROWS(ALLNOBLANKROW('商品表'[售价]))

ALL_售价:=COUNTROWS(ALL('商品表'[售价]))

  还是那句话,如果你对ALLNOBLANKROW处理由参照完整性不匹配而产生的空行的行为不理解的话,可以看我的上篇文章:5、DAX的常用表函数之VALUES与DISTINCT,上面的例子用的数据也是上篇文章的,而我在上篇文章里已经详细讲解过了,这里就不再重复讲解,因为ALLNOBLANKROW处理由参照完整性不匹配而产生的空行的行为与DISTINCT一致。

3.3 ALLCROSSFILTERED

  ALLCROSSFILTERED的作用仅仅只是ALL的一小部分,它的语法结构与函数作用如下:

  • 语法:
ALLCROSSFILTERED ( <TableName> )
  • 作用:

  ALLCROSSFILTERED只能用作筛选调节器,而不能用作表函数,将移除参数所指定的表的扩展表上的所有筛选器。

  ALLCROSSFILTERED的作用与ALL用作筛选调节器时的行为一致,但ALLCROSSFILTERED的参数只能接受表,而不能接受列作为它的参数。所以,一般情况下都是使用ALL而不使用ALLCROSSFILTERED。由于ALLCROSSFILTERED的行为与ALL一致,因此不再继续讲解,可以参照上文中ALL的应用示例。

3.4 REMOVEFILTERS

  REMOVEFILTERS从名字上看好像不属于ALL类函数,但其实它是ALL的别名。REMOVEFILTERS接受的参数与ALL一致,但它的功能仅仅只有ALL的一半。语法结构与函数作用具体如下:

  • 语法:
REMOVEFILTERS ( <TableName> | <ColumnName> , [ <ColumnName>, [ <ColumnName>, [ … ] ] ] )
  • 作用:

  REMOVEFILTERS只能用作筛选调节器,而不能用作表函数,将移除参数所指定的表的扩展表或指定的列上的所有筛选器,不会返回任何值。

  由于ALL函数可以用作表函数也可以用作筛选调节器,这使得ALL在一些复杂的公式中的作用变得难以识别。因此,当需要把ALL用作筛选调节器时,可以使用REMOVEFILTERS来代替。由于REMOVEFILTERS的行为与ALL一致,因此不再继续讲解,可以参照上文中ALL的应用示例。

3.5 ALLSELECTED

  ALLSELECTED将在下一篇文章中进行讲解,在这里先给出ALLSELECTED的语法结构与作用,具体如下:

  • 语法:
ALLSELECTED ( [<TableName> | <ColumnName>] )
  • 作用:

  1、用作表函数时,将返回参数所指定的表或列在最后一个影子筛选上下文里的筛选结果;

  2、用作筛选调节器时,将激活参数所指定的表或列的最后一个影子筛选上下文,如果不存在影子筛选上下文,那么将不执行任何操作;

四、总结

  在DAX中,ALL类函数的作用是非常重要的,因为这些函数能够修改扩充计值环境,所以必须充分理解ALL类函数的每一个细节,这样才能更好地掌控计值流程。建议在阅读完本文后多做测试,以尽可能地掌握ALL类函数的每一个细节。

  对DAX的学习其实就是对计值流程的学习,归根到底其实就是对理论的学习。“技巧无穷尽,理论统御之”,我觉得这是对DAX最好的描述,只要你掌握了理论,那么你就掌握了DAX!

展开阅读全文
  • 4
    点赞
  • 0
    评论
  • 10
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值