前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Power BI: 理解ALLSELECTED函数和影子筛选上下文

Power BI: 理解ALLSELECTED函数和影子筛选上下文

作者头像
Exploring
发布2023-09-10 15:40:53
5810
发布2023-09-10 15:40:53
举报

ALLSELECTED函数是唯一一个使用影子筛选上下文的DAX函数。我们首先研究ALLSELECTED的行为,然后介绍影子筛选上下文。

1 ALLSELECTED的行为2 影子筛选上下文介绍3 ALLSELECTED返回迭代的行4 无参数的ALLSELECTED函数

1 ALLSELECTED的行为

ALLSELECTED可以非常被直观地使用。例如,观察图1所示的报表。

图1 不同地区的销售总额及其占比

计算占比和销售总额使用的公式如下:

代码语言:javascript
复制
占比 = 
DIVIDE(
    [销售总额],
    CALCULATE(
        [销售总额],
        ALLSELECTED('销售记录'[地区])
        )
    )
    
销售总额 = sum('销售记录'[销售额])

直觉上,读者很可能已经猜到ALLSELECTED返回的是当前视觉对象之外选择的地区,也就是从东北到华南之间的所有地区。但Power BI发送给DAX的只是一个DAX引擎,并不存在当前视觉对象的概念。

对ALLSELECTED的正确定义包括以下两个部分:

  • 当作为表函数使用时,ALLSELECTED返回的是最后一个影子筛选上下文中的可见值。
  • 当作为CALCULATE调节器使用时,ALLSELECTED将还原其参数上的最后一个影子筛选上下文

这两句话值得我们详细解释。

2 影子筛选上下文介绍

为了介绍影子筛选上下文,我们先看一个查询。

代码语言:javascript
复制
Evaluate
VAR Areas =
                FILTER(
                                ALL( '销售记录'[地区] ),
                                '销售记录'[地区]
                                            in {
                                                        "东北",
                                                        "华北",
                                                        "华南"
                                                    }
                                )
RETURN
            CALCULATETABLE(
                        ADDCOLUMNS(
                                        VALUES( '销售记录'[地区] ),
                                        "销售总额", [销售总额],
                                        "占比",[占比]
                        ),
                        Areas
           )

这个查询的结果与我们前面展示的报表几乎相同,只是少了一个总计行。在图2中可以看到这一点。

图2 查询提供的结果与前面的报表几乎相同,唯一缺少的是总计行

下面我们对查询的执行过程做详细的描述,并在步骤3中引入影子筛选上下文。

  1. 外层CALCULATETABLE创建一个包含3个地区的筛选上下文。
  2. VALUES返回3个可见地区,并将结果返回给ADDCOLUMNS。
  3. 作为迭代函数的ADDCOLUMNS,在迭代开始前,创建一个包含VALUES结果的影子筛选上下文。
    • 影子筛选上下文类似于筛选上下文,但它保持休眠状态,不会以任何方式参与影响计算。
    • 影子筛选上下文只能被ALLSELECTED激活。
    • 为了区分影子筛选上下文和普通的筛选上下文。我们将后者称为显式筛选上下文
  4. 在迭代期间,上下文转换发生在一个给定的行上。因此,上下文转换创建一个新的显式筛选上下文,其中只包含要迭代的地区
  5. 当在占比的度量值中调用ALLSELECTED时,ALLSELECTED执行以下操作:ALLSELECTED恢复作为参数传递的列上的最后一个影子筛选上下文
    • 因为最后一个影子筛选上下文包含3个地区,所以切片器选择的所有地区再次可见。

这个简单的例子帮助我们引入了影子筛选上下文的概念。前面的查询展示了ALLSELECTED如何利用影子筛选上下文来检索当前视觉对象之外的筛选上下文。

在读者对ALLSELECTED的理解更进一步之前,我们现在先来更仔细地研究ALLSELECTED正常计值所需要的条件。

  • 查询需要一个迭代函数
  • 如果在ALLSELECTED执行前存在多个迭代函数,那么ALLSELECTED会恢复最后一个影子筛选上下文。
  • 如果传递给ALLSELECTED的列没有被影子筛选上下文筛选,那么ALLSELECTED就没有任何作用。

ALLSELECTED的最佳实践很简单:当且仅当ALLSELECTED被直接置于矩阵或视觉对象中的度量值调用时,它才可以用来检索外部筛选上下文。

3 ALLSELECTED返回迭代的行

为了进一步演示ALLSELECTED的行为,我们对前面的查询做一个小改动——不再迭代VALUES( '销售记录'[地区] ),而是让ADDCOLUMNS迭代ALL( '销售记录'[地区] )。

代码语言:javascript
复制
Evaluate
VAR Areas =
            FILTER(
                        ALL( '销售记录'[地区] ),
                        '销售记录'[地区]
                                    in {
                                                "东北",
                                                "华北",
                                                "华南"
                                            }
            )
    
RETURN
            CALCULATETABLE(
                            ADDCOLUMNS(
                                        ALL( '销售记录'[地区] ),
                                        "销售总额", [销售总额],
                                        "占比",[占比]
                             ),
                            Areas
                )

图3 ALLSELECTED恢复当前迭代的所有值,而不是之前的筛选上下文

ALLSELECTED返回最后一个影子筛选上下文;在修改后的查询中,最后一个影子筛选上下文包含所有地区,而不仅仅是筛选后的地区。

如果需要保留之前的筛选上下文,就不能只依靠ALLSELECTED。保留之前的筛选上下文的CALCULATE调节器是KEEPFILTERS。

代码语言:javascript
复制
Evaluate
VAR Areas =
            FILTER(
                        ALL( '销售记录'[地区] ),
                        '销售记录'[地区]
                            in {
                                        "东北",
                                        "华北",
                                        "华南"
                                    }
            )
    
RETURN
                CALCULATETABLE(
                            ADDCOLUMNS(
                                        KEEPFILTERS( ALL( '销售记录'[地区] ) ),
                                        "销售总额", [销售总额],
                                        "占比",[占比]
                            ),
                            Areas
                 )

图4 ALLSELECTED和KEEPFILTERS一起使用产生另一种结果,包含很多空行

当KEEPFILTERS作为迭代函数的调节器使用时,它不会改变被迭代表的结果。而是指示迭代函数在迭代表的过程中,每当发生上下文转换时,将KEEPFILTERS作为隐式CALCULATE调节器应用到度量值中。虽然查询返回所有的地区,但计算最终结果时,只考虑了所选的地区。

再来看一个关于KEEPFILTERS的例子。

test度量值表示如下:

代码语言:javascript
复制
test = 
sumx(
    KEEPFILTERS( all('销售记录'[地区]) ),
    CALCULATE( [销售总额], ALLSELECTED('销售记录'[地区]) )
    )

图5 度量值test返回的结果都是400

在度量值test中引入新的迭代器SUMX,迭代所有的地区。在迭代计算每一个地区时,由于 KEEPFILTERS函数的存在,考虑了切片器所选的地区,因此计算结果是80,迭代计算5个地区,所以最终的计算结果是400。

建议:你应该尽量避免使用影子筛选上下文,并且千万不要在迭代中调用包含ALLSELECTED的公式。在ALLSELECTED之前可以出现的唯一迭代是由查询引擎(主要是Power BI客户端)创建的最外层迭代。在迭代内部调用ALLSELECTED的度量值会使计算更加复杂。

4 无参数的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

本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-08-20,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 数据处理与编程实践 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 ALLSELECTED的行为
  • 2 影子筛选上下文介绍
  • 3 ALLSELECTED返回迭代的行
  • 4 无参数的ALLSELECTED函数
相关产品与服务
腾讯云 BI
腾讯云 BI(Business Intelligence,BI)提供从数据源接入、数据建模到数据可视化分析全流程的BI能力,帮助经营者快速获取决策数据依据。系统采用敏捷自助式设计,使用者仅需通过简单拖拽即可完成原本复杂的报表开发过程,并支持报表的分享、推送等企业协作场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com