PowerBI之DAX神功:第1卷第16回 创建筛选上下文与Filter+ALL应用
《DAX神功》第1卷第12回 我们学习了创建行上下文可以使用迭代函数,例如sumx等
DAX中有两个函数可以创建筛选上下文:Calculate和Calculatetable
二者区别:Calculate返回值,Calculatetable返回表
接下来,我们以Calculate为例,进行介绍:
一、创建筛选上下文



例如:我们需要计算,同比增长率=(本期-同期)/ 同期
同比增长率1 =
VAR tb1=FILTER('销售表','销售表'[日期]="本期")
VAR B=sumx(tb1,'销售表'[销售数量]*RELATED('商品表'[售价]))
VAR tb2=FILTER('销售表','销售表'[日期]="同期")
VAR T=sumx(tb2,'销售表'[销售数量]*RELATED('商品表'[售价]))
return
DIVIDE((B-T),T)
将度量值放到矩阵中:

《The Definitive Guide to DAX》中指出上面的代码不优雅,它认为下面的代码优雅:
销售金额 = sumx('销售表','销售表'[销售数量]*RELATED('商品表'[售价]))
同比增长率2 =
VAR B=CALCULATE([销售金额],'销售表'[日期]="本期")
VAR T=CALCULATE([销售金额],'销售表'[日期]="同期")
return
DIVIDE((B-T),T)
我们可以合并这两个度量值
同比增长率2 =
VAR B=CALCULATE(sumx('销售表','销售表'[销售数量]*RELATED('商品表'[售价])),'销售表'[日期]="本期")
VAR T=CALCULATE(sumx('销售表','销售表'[销售数量]*RELATED('商品表'[售价])),'销售表'[日期]="同期")
return
DIVIDE((B-T),T)
然而同比增长率1,书中是故意分成多行写的,让你看上去很繁琐,你将TB变量都放到sumx
同比增长率1 =
VAR B = sumx(FILTER('销售表','销售表'[日期]="本期"),'销售表'[销售数量]*RELATED('商品表'[售价]))
VAR T = sumx(FILTER('销售表','销售表'[日期]="同期"),'销售表'[销售数量]*RELATED('商品表'[售价]))
return
DIVIDE((B-T),T)
这叫视觉假像:例如下图是一个静态图片,但是你可能会看到它在动

但是问题并不是出现在代码优雅上面,而是筛选上下文作用于整个模型
也许它在实际分析中的意义不大,但是你要知道他的区别。虽然两个同比增长率都不能够使用日期筛选,但是通过创建筛选上下文返回的值是正确的,同比增长率2只是日期列被取消了筛选。

二、Calculate另一种写法和秘密
讲这个知识之前,我们要先回忆《DAX神功》第1卷第14回讲的变形金刚,我们已经推导了这种写法的由来

例如:拿到销售表中本期所有行的表
【新建表】新表 = FILTER(ALL('销售表'),'销售表'[日期]="本期")
解读:从销售表中筛选日期是"本期"的所有行数据。(将这张表做为筛选条件放到Calculate筛选器中任何字段都不能筛选,因为ALL(表))

例如:拿到销售表中日期列本期表
新表 = FILTER(ALL('销售表'[日期]),'销售表'[日期]="本期")
解读:从销售表的日期列中找到本期。(将这张表做为筛选条件放到Calculate筛选器中只有日期列不能筛选,因为ALL(列))

我们通过上述过程,书写以下度量值:
本期销量1 = CALCULATE([总销量],'销售表'[日期]="本期")
本期销量2 = CALCULATE([总销量],filter(all('销售表'[日期]),'销售表'[日期]="本期"))
本期销量3 = CALCULATE([总销量],filter(all('销售表'),'销售表'[日期]="本期"))

现在问题来了:以下3个度量值是等价的吗?
本期销量1 = CALCULATE([总销量],'销售表'[日期]="本期")
本期销量2 = CALCULATE([总销量],filter(all('销售表'[日期]),'销售表'[日期]="本期"))
本期销量4 = CALCULATE([总销量],FILTER('销售表','销售表'[日期]="本期"))

本期销量1与本期销量2是等价的,但是与本期销量4是不一样的,这又是为什么呢?
本期销量2 = CALCULATE([总销量],filter(all('销售表'[日期]),'销售表'[日期]="本期"))
本期销量2,由于我们使用了all(列),它不能使用日期筛选是正常的。
本期销量4 = CALCULATE([总销量],FILTER('销售表','销售表'[日期]="本期"))
本期销量4,我们没有使用all函数,他可以筛选也是正常的。
【不正常的是本期销量1】
本期销量1 = CALCULATE([总销量],'销售表'[日期]="本期")
本期销量1,我们没有使用all函数,但是它仍然无法使用日期筛选
这个问题,我们下回再说。

《DAX神功》文字版合集,同步更新中:
https://www.bilibili.com/read/readlist/rl442274
《DAX神功》视频版合集,同步更新中:
https://www.bilibili.com/video/BV1YE411E7p3
更多教程合集:
PowerBI(DAX函数)、PowerQuery(M函数)、Python办公自动化、Python爬虫、Python数据分析、ExcelVBA、WordVBA、AccessVBA、MySQL等等