从数据到信息
从信息到洞察

理解 CALCULATETABLE

理解 CALCULATETABLE

CALCULATETABLECALCULATE 的工作方式相同,语法可以参考 CALCULATE ,唯一的区别在于结果的类型:

CALCULATE 计算标量值,而 CALCULATETABLE 计算返回表的表达式,并返回一个表

继续上一篇文章,下面的公式正是我们需要的:它移除了品牌和颜色两个维度的筛选上下文,但是让其他筛选器进入 FILTER 函数内部。

[CalcTable Version] :=
CALCULATE (
    SUM ( Sales[SalesAmount] ),
    FILTER (
        CALCULATETABLE (
            Product,
            ALL ( Product[Brand] ),
            ALL ( Product[Color] )
        ),
        AND (
            Product[Brand] = "Tailspin Toys",
            Product[Color] = "Black"
        )
    )
)

如图所示,CalcTable 版本的公式计算了正确的值,与 CALCULATE 版本返回的值相同。

通过使用 CALCULATETABLE 得到了正确的结果

这段关于等效结果转换的题外讨论很重要,因为掌握将布尔筛选器转换为等效 FILTER 函数的技术将极大地帮助你处理更复杂的情况。例如,如果你想要表达一个 OR 条件,而不是 AND,就需要用到这种方法。

例如,如果想计算品牌是 Tailspin Toys 或颜色是黑色(OR 条件)的所有产品的销售额,那么你需要使用 CALCULATETABLE,代码如下所示:

[CalcTable Version OR] :=
CALCULATE (
    SUM ( Sales[SalesAmount] ),
    FILTER (
        CALCULATETABLE (
            Product,
            ALL ( Product[Brand] ),
            ALL ( Product[Color] )
        ),
        OR (
            Product[Brand] = "Tailspin Toys",
            Product[Color] = "Black"
        )
    )
)

实际上,使用 CALCULATETABLE 函数从品牌和颜色中删除筛选器是一种便利的方式,可以保持其他筛选器不受影响。因此,有许多列的条件取 AND 时可以很容易地通过简单的 CALCULATE 来解决,因为 CALCULATE 自动对所有的筛选器参数取交集。而另一方面,不同列之间的 OR 条件要复杂得多,因为你不能依赖于 CALCULATE 自动取交集的行为,需要手动编写复杂的 DAX 代码。

值得注意的是,你还可以使用以下代码作为替代公式,它使用一个两列的 ALL 函数:

[ALL Version OR] :=
CALCULATE (
    SUM ( Sales[SalesAmount] ),
    FILTER (
        ALL (
            Product[Brand],
            Product[Color]
        ),
        OR (
            Product[Brand] = "Tailspin Toys",
            Product[Color] = "Black"
        )
    )
)

后一种表达式更优雅,但一开始你可能觉得它不是很直观。

在本文中,你已经看到,一旦使用了多个列,或者通常情况下更复杂的条件,结果将变得难以理解。即使是经验丰富的 DAX 程序员也常常发现很难领会计值流。因此,不要畏惧本章的复杂性;只有积累丰富的经验才能引导你学会如何快速阅读并通晓 DAX 公式。

关于最后这种筛选多列的情景,请读者配合理解 CALCULATE 一文中的最后一节复杂筛选扩展进行理解,此节列举了多列筛选的各种常见情况以及优劣分析

小测试

CALCULATETABLE 对表进行操作,比如你可以用它筛选出 Sales 表中特定产品类别的所有销售记录,很多新人经常会犯的一个错误是直接把 CALCULATETABLE 筛选后的结果用作度量值,比如下面的公式:

Wrong_Measure =
CALCULATETABLE ( Sales, Sales[Category] = "TV" )

这是错误的写法,原因是度量值只能返回标量结果(单个值),而不能返回表,如果你将上面的公式定义到度量值中,会收到错误提示:

该表达式引用多列,多列不能转换为标量值

假设你最终计算的是所有 TV 产品销售记录的最近日期,你需要将 CALCULATETABLE 得到的结果用做筛选器参数,或使用迭代函数进行取值,公式写法:

公众号二维码加载失败时的替代文字
此处内容已经被作者无情的隐藏,请输入验证码查看内容
验证码:
请关注“PowerBI极客”公众号,回复关键字“CT”,获取验证码。 【注】手机扫描二维码快速关注“PowerBI极客”官方公众号。

CALCULATETABLE vs FILTER

CALCULATETABLE 和 FILTER 都可以对表进行筛选,是两个最常用的表函数,了解两者之间的差异有助于你不同场景下选择正确的函数。

本文隐藏内容查看价格为2G币,请先
单独购买的内容长期有效,不受时间限制(购买前先刷新当前页面)。加入VIP会员可享受全站权益,性价比更高。

 

18
说点什么

1000
 
鼓掌微笑开心憧憬爱你色并不觉得吃瓜doge二哈喵喵思考笑哭捂脸悲伤大哭抓狂汗偷笑打脸捂眼黑线问号晕拜拜闭嘴衰咒骂ok作揖
7 评论数
11 被回复的评论
7 订阅评论的人数
 
查看最近回复
查看最热评论
  订阅本文评论  
最新 最旧 得票最多
提醒
游客
李是

老师,这个函数的执行顺序是咋样的

游客
芝芝

老师 我看到时间智能函数的时候,发现这个公式calculatetable(distinct(‘Date'[date]’)),书上说是将引用列转换成表,但distinct本就返回的是表啊?为什么还需要用到calculatetable啊?

成员
山石琢玉

精彩,我看了3天,看懂了

成员
139****3194

老师,本文第一个度量值calctable version 的计值流是这样吗?
1.取消初始筛选器为品牌和颜色的(如果有的话),其它初始筛选器保留筛选(例如有类别列的话);同时这里两个all相当于调节器;
2.filter 第一参形成产品表,品牌和颜色列无筛选器,其它产品表列可能有筛选器,视透视表环境而定;
3.在第2步基础上逐行迭代,形成最新表筛选上下文(品牌和颜色覆盖透视表行标签里相同字段,同时保留透视表其它筛选器),最后取交集。

感觉越来越难,不太相信自己理解,望指正。谢谢

成员
139****3194

老师,请问productsSlow这个度量值里,filter里的value 形成单列不重复表会被透视表的来自维度表的不同列先筛选吗?筛选后再进入filter迭代每行吗?

成员
lyliuyouyang

但必须注意的是,CALCULATETABLE 始终执行上下文转换,这是它和 FILTER 的一个最大区别,请问这句话的意思是什么?filter也是迭代函数,会考虑第一参数的行上下文,感觉没什么差别,我个人的理解是filter会考虑外部上下文

成员
pingzi111

你好,倒数第二段话:“有一种特殊情况是在 CALCULATETABLE 使用并列的多个 FILTER 作为筛选器:”是描述CALCULATE的吗,因为我看下面的DAX公式里面只有CALCULATE没有CALCULATETABLE。看的懵懵的 衰

DAX 圣经

导读

初识 DAX

DAX 基础知识

DAX 原理

DAX 高级原理

基础函数类型

迭代函数

CALCULATE 函数

CALCULATE 调节器

基础表函数

条件判断函数

查找匹配函数

时间智能函数

统计类函数

投影函数

分组/连接函数

集合函数

其他函数