ALLSELECTED函数是唯一一个使用影子筛选上下文的DAX函数。我们首先研究ALLSELECTED的行为,然后介绍影子筛选上下文。
1 ALLSELECTED的行为2 影子筛选上下文介绍3 ALLSELECTED返回迭代的行4 无参数的ALLSELECTED函数
ALLSELECTED可以非常被直观地使用。例如,观察图1所示的报表。
图1 不同地区的销售总额及其占比
计算占比和销售总额使用的公式如下:
占比 =
DIVIDE(
[销售总额],
CALCULATE(
[销售总额],
ALLSELECTED('销售记录'[地区])
)
)
销售总额 = sum('销售记录'[销售额])
直觉上,读者很可能已经猜到ALLSELECTED返回的是当前视觉对象之外选择的地区
,也就是从东北到华南之间的所有地区。但Power BI发送给DAX的只是一个DAX引擎,并不存在当前视觉对象
的概念。
对ALLSELECTED的正确定义包括以下两个部分:
这两句话值得我们详细解释。
为了介绍影子筛选上下文,我们先看一个查询。
Evaluate
VAR Areas =
FILTER(
ALL( '销售记录'[地区] ),
'销售记录'[地区]
in {
"东北",
"华北",
"华南"
}
)
RETURN
CALCULATETABLE(
ADDCOLUMNS(
VALUES( '销售记录'[地区] ),
"销售总额", [销售总额],
"占比",[占比]
),
Areas
)
这个查询的结果与我们前面展示的报表几乎相同,只是少了一个总计行。在图2中可以看到这一点。
图2 查询提供的结果与前面的报表几乎相同,唯一缺少的是总计行
下面我们对查询的执行过程做详细的描述,并在步骤3中引入影子筛选上下文。
地区
,并将结果返回给ADDCOLUMNS。地区
。占比
的度量值中调用ALLSELECTED时,ALLSELECTED执行以下操作:ALLSELECTED恢复作为参数传递的列上的最后一个影子筛选上下文。地区
再次可见。这个简单的例子帮助我们引入了影子筛选上下文的概念。前面的查询展示了ALLSELECTED如何利用影子筛选上下文来检索当前视觉对象之外的筛选上下文。
在读者对ALLSELECTED的理解更进一步之前,我们现在先来更仔细地研究ALLSELECTED正常计值所需要的条件。
ALLSELECTED的最佳实践很简单:当且仅当ALLSELECTED被直接置于矩阵或视觉对象中的度量值调用时,它才可以用来检索外部筛选上下文。
为了进一步演示ALLSELECTED的行为,我们对前面的查询做一个小改动——不再迭代VALUES( '销售记录'[地区] ),而是让ADDCOLUMNS迭代ALL( '销售记录'[地区] )。
Evaluate
VAR Areas =
FILTER(
ALL( '销售记录'[地区] ),
'销售记录'[地区]
in {
"东北",
"华北",
"华南"
}
)
RETURN
CALCULATETABLE(
ADDCOLUMNS(
ALL( '销售记录'[地区] ),
"销售总额", [销售总额],
"占比",[占比]
),
Areas
)
图3 ALLSELECTED恢复当前迭代的所有值,而不是之前的筛选上下文
ALLSELECTED返回最后一个影子筛选上下文;在修改后的查询中,最后一个影子筛选上下文包含所有地区,而不仅仅是筛选后的地区。
如果需要保留之前的筛选上下文,就不能只依靠ALLSELECTED。保留之前的筛选上下文的CALCULATE调节器是KEEPFILTERS。
Evaluate
VAR Areas =
FILTER(
ALL( '销售记录'[地区] ),
'销售记录'[地区]
in {
"东北",
"华北",
"华南"
}
)
RETURN
CALCULATETABLE(
ADDCOLUMNS(
KEEPFILTERS( ALL( '销售记录'[地区] ) ),
"销售总额", [销售总额],
"占比",[占比]
),
Areas
)
图4 ALLSELECTED和KEEPFILTERS一起使用产生另一种结果,包含很多空行
当KEEPFILTERS作为迭代函数的调节器使用时,它不会改变被迭代表的结果。而是指示迭代函数在迭代表的过程中,每当发生上下文转换时,将KEEPFILTERS作为隐式CALCULATE调节器应用到度量值中。虽然查询返回所有的地区,但计算最终结果时,只考虑了所选的地区。
再来看一个关于KEEPFILTERS的例子。
test度量值表示如下:
test =
sumx(
KEEPFILTERS( all('销售记录'[地区]) ),
CALCULATE( [销售总额], ALLSELECTED('销售记录'[地区]) )
)
图5 度量值test返回的结果都是400
在度量值test
中引入新的迭代器SUMX
,迭代所有的地区。在迭代计算每一个地区时,由于 KEEPFILTERS函数的存在,考虑了切片器所选的地区,因此计算结果是80,迭代计算5个地区,所以最终的计算结果是400。
建议:你应该尽量避免使用影子筛选上下文,并且千万不要在迭代中调用包含ALLSELECTED的公式。在ALLSELECTED之前可以出现的唯一迭代是由查询引擎(主要是Power BI客户端)创建的最外层迭代。在迭代内部调用ALLSELECTED的度量值会使计算更加复杂。
当用作CALCULATE调节器时,与ALL一样,ALLSELECTED也可以在没有任何参数的情况下使用。在这种情况下,ALLSELECTED将恢复任何列上的最后一个影子筛选上下文。
请记住,当且仅当列被包含在任何影子筛选上下文中时,才会发生这种情况。如果仅通过显示筛选器筛选列,那么筛选器保持不变。
参考资料:
[1] DAX权威指南(https://item.jd.com/13168782.html)
[2] 深入理解 Power BI DAX 中 ALLSELECTED 的影子筛选器(https://blog.csdn.net/qingmeizhujiu8/article/details/125425355)