参考资料:https://www.powerbigeek.com/understanding-allselected-function/
这篇文章关于ALLSELECTED的原理描述参考上述链接,根据自己的理解总结而成,与上述链接并不完全一致,并不保证自己的理解完全正确,但在试验中这样子理解是没有问题的。
一张“sheet”表如下。
建几个度量值,并放入矩阵中:
sum =SUM(sheet[value])
all =CALCULATE([sum],ALL(sheet[color]))
allselected =CALCULATE([sum],ALLSELECTED(sheet[color]))
allexcept = CALCULATE([sum],ALLEXCEPT(sheet,sheet[brand]))
可以看到‘sum’度量值是受切片器color,行标签brand和行标签color筛选后的计算,
而‘all’和‘allexcept’的结果一致,是移除color筛选器(包括切片器和行标签)后的计算,此时只有行标签brand筛选器存在,
而‘allselected’是移除了行标签color筛选器后的计算,此时切片器color和行标签brand筛选器仍然存在。
all表=CALCULATE([sum],ALL(sheet))
allselected表=CALCULATE([sum],ALLSELECTED(sheet))
可以看到‘all表’度量值移除了切片器color、行标签color、行标签brand筛选器,也就是移除了对sheet表的所有筛选器,
而‘allselected表’度量值移除了所有筛选器,但是保留了切片器所在的筛选器。
总结:当DAX表达式不是很复杂时(没有多层嵌套),可以简单的理解为:
ALL(列名)是移除表上指定的列名所包括的筛选器(包括切片器和行列标签),
ALL(表名)是移除表上的所有筛选器(包括切片器和行列标签),
ALLEXCEPT(表名,列名)是移除表上的所有筛选器(包括切片器和行列标签),只保留指定列名包括的筛选器,
ALLSELECTED(列名)是移除指定列的筛选器,但是保留切片器筛选器,
ALLSELECTED(表名)是移除所有筛选器,除了切片器筛选器。
但是当DAX表达式有多层嵌套时,就会发现这样理解是不够正确的。
首先理解交叉筛选:
图中没有对product列应用任何筛选器,只有切片器color筛选器,但是通过切片器,仍然能够对product列进行筛选,此时product列就是受到交叉筛选的影响。
其次,我把筛选器分成两类,一类是用作数据筛选的筛选器,一类是用作数据呈现的筛选器。
如上图所示,矩阵中的product标签就是用作数据呈现的筛选器,而切片器color就是用作数据筛选的筛选器。
我们可以说矩阵中的第一个值有两个筛选条件,一个是color等于green,一个是product等于heimet,事实上数据始终只受了切片器color的影响,筛选出了color等于green的记录,此时我们可以有不同的数据呈现方式,可以按照不同的product去聚合呈现(也就是图中的方式),也可以把数据直接聚合成一个值等等。
矩阵中的行列标签,sumx、filter、addcolumn这些迭代函数(迭代函数的第一参数会创建行上下文,当被封装在calculate中时可以转为筛选上下文,此时它们就是用作数据呈现的筛选器)都是用作数据呈现的筛选器。
ALL、ALLSELECTED、ALLEXCEPT都有两个作用,一是用来移除筛选器(写在calculate的筛选条件里),二是用来返回表(作为filter、sumx等函数的第一参数)。
在接触DAX时我们了解到PowerBI中的数据是以列为形式存储的,同样的移除筛选器也是以列为单位的,ALL这些函数只能移除掉直接应用于该列上的筛选器,而不考虑交叉筛选的影响(比如ALL(sheet[product])可以移除掉'sheet'[product] in
{"shoes","robot"}的筛选,却不能移除掉'sheet'[color] in {"blue","red"}对product列的交叉筛选),并且如果对该列多次应用筛选器,后来的筛选器总会覆盖之前的筛选器。
在复杂的DAX中往往要嵌套好几层条件,它们是有先后顺序的,分开来看的话可以说存在多个筛选出来的记录表,那么移除的是哪张表上的筛选器呢?ALL和ALLSELECTED有不同的回答。
度量值8 = CALCULATE(CALCULATE([sum],ALLSELECTED(sheet[product])),'sheet'[product] in{"shoes","robot"})
度量值9 = CALCULATE(SUM(sheet[value]),'sheet'[product] in{"shoes","robot"})
度量值2 = CALCULATE(CALCULATE([sum],ALL(sheet[product])),'sheet'[product] in{"shoes","robot"})
以打红框的bike这行为例:
先来看‘度量值8’。首先没有切片器的筛选,然后行标签为product列应用了一个筛选器,即product等于bike,在计算时calculate中的条件'sheet'[product] in
{"shoes","robot"}也在product列应用了一个筛选器,这个筛选器无疑会覆盖之前的筛选器,也就是说此时只有product列上有一个筛选器即product等于shoes或robot(暂且把它记为表1,表1中只有product一列),而在calculate的表达式中嵌套了一个calculate,其中的条件是ALLSELECTED(sheet[product]),此时ALLSELECTED的作用是移除表1上的product列的筛选器,这里就得说到ALLSELECTED只移除用作数据呈现的筛选器,显然这里没有,也就是最后只有筛选器表1,根据隐藏的索引列可以找到表1对应的value列,把值加总就是497.
再看‘度量值2’。不同于ALLSELECTED移除的是针对最后一个筛选表的用作数据呈现的筛选器,ALL移除的是针对源表(或源表中的一列)的所有筛选器。首先,切片器没有对源表中的product列应用筛选器,而行标签对源表中的product列应用了一个筛选器即product等于bike,而'sheet'[product] in {"shoes","robot"}覆盖了这个筛选器,也就是此时源表的product列的筛选器为product等于shoes或robot,而ALL(sheet[product])移除了源表product列的所有筛选器,所以此时product列没有任何筛选器,依据product列找到相应的value列的值加总就是2705。
作用是返回表的ALLSELECTED。
ALLSELECTED(product):移除表上的用作数据呈现的筛选器,然后返回此时表中的所有记录。这里显然是没有这类筛选器的,所以返回Product[Color] IN { "Blue", "Green"
},Product[Brand] IN { "Contoso", "Fabrikam" }组成的筛选表,只有四行记录。
ALLSELECTED(product[product]):移除product列上的用于数据呈现的筛选器,然后返回此时该列去重复后的所有值。因为条件中只对color列和brand列应用过筛选器,所以product列的筛选表还是源表的product列,而且这里没有用于数据呈现的筛选器,所以最后返回的是源表中的product列的去重复值,也就是9个产品。