PowerBI之DAX神功:第1卷第8回 基础表函数之ALL与ALLEXCEPT函数
这是我们上节课的两个度量值公式:
通过四级人员的成绩 = calculate(sum('成绩表'[平时成绩]),filter('学生表','学生表'[四级]="通过"))
考试学生有多少人= Calculate(CountRows('学生表'), '成绩表')
Calculate的筛选器可以用Filter,同时也可以使用一张表,因为Filter返回的就是一张表。ALL函数返回也是一张表,它也是表函数,但是它与Filter相反。
Filter是筛选,ALL是全选
关于calculate第二参数筛选器,为什么可以是多端表,马上打脸。
接下来,我们看这节课的知识:这张表的表名是'Sheet1'

图1-8-1,我想计算每个人的捐款占比,那我要先知道他们三个人一共捐了多少钱?

如图1-8-2,张三10+李四20+王五30=总计60
想实现上表我们可以使用【新建列】
总捐款 = sum('Sheet1'[捐款])
//新建列是行上下文无筛选功能
占比 = 'Sheet1'[捐款]/'Sheet1'[总捐款]
现在多增加一个没有用的列,无形当中占用了内存和硬盘
我们可以省略总捐款这个列写成这样
占比 = 'Sheet1'[捐款]/60

但是这个60是人算出来的,为了能将它写活,我们新建【度量值】
固定值 = CALCULATE(sum([捐款]),all('Sheet1'))
在新建列中使用度量值:如图1-8-3
占比 = 'Sheet1'[捐款]/[固定值]

为了更好的理解ALL(表),我们回到Excel中做这件事:

如图1-8-4,我们想实现占比,就要算出三个人捐款总和,再用每个人的捐款金额除以捐款总和,我们在单元格操作时,会用到绝对引用,保证除数是固定值。如图1-8-5

$D$5这个单元格就是除数同时也是我们的度量值固定值:
固定值 = CALCULATE(sum([捐款]),all('Sheet1'))
ALL函数当参数为表时,它返回这张表中所有的行,就好比Excel中的绝对引用。现在我们分析这个度量值:
【1】sum([捐款])是Calculate引擎中的计算器,它是一个吃饭用的碗,里面放着三个人捐款的钱。
【2】而all('Sheet1')是引擎中的筛选器,它代表这个表中的所有行,也就是说这张表中所有行的钱数总计是多少。
是不是与我们上节课讲的Filter正好是相反的?
如果我们使用Filter('Sheet1','Sheet1'[性别]='男')做为筛选器,它只会从sum([捐款])这个度量值中拿出所有男生的捐款金额。而all('Sheet1')是拿所有人的。所以,我说Filter是筛选,ALL是全选。

接来下,我们尝试在矩阵中实现,分别建立3个度量值:图1-8-6
总捐款=sum('Sheet1'[捐款])
固定值=CALCULATE([总捐款],all('Sheet1'))
占比 = [总捐款]/[固定值]

实际情况并不需要固定值这个度量值,我们目的是计算占比:
占比2 =
VAR x = sum('Sheet1'[捐款])
VAR y= CALCULATE(sum('Sheet1'[捐款]),all('Sheet1'))
return
x/y


之前我们只有一张表,如果多张表,应该考虑哪些问题呢?


虽然有5名学生,但是只有3人参与捐款,因为捐款是自愿的。
我们使用这3个度量值:
总捐款 = sum('捐款表'[捐款])
固定值 = CALCULATE([总捐款],all('捐款表'))
占比 = [总捐款]/[固定值]

学号字段来自多端表:捐款表
现在打第1下脸:如图1-8-7
有人提问:Calculate第二参数为什么不能是多端表?
我反问你:我要捐款表中的所有行,有问题吗?
一端筛选多端我一直在矩阵上举例与Calcaulate有什么关系?
大清亡了,跟关羽去世有关系吗?关羽不是清朝的!
我们再啰嗦一遍CALCULATE
CALCULATE(计算器,筛选器)
计算器得到的是一个数字,我们从数字中提取满足条件的那一部分,例如,计算器是男女生人数总和,筛选器筛选男生人数。就讨论这件事与一端多端有什么联系?没联系!

现在打第2下脸:将行标题换成学生表中的姓名后就变成了这个样子

【总捐款】这个度量值是对捐款表中捐款那一列的聚合,捐款表中没有邓七和赵六,所以这个度量值在筛选时,不显示邓七和赵六的值。
【固定值】这个度量值,其实就是那个$D$5单元格,永恒不变的固定值。
当我们将行标题换成学生表中的姓名时,邓七和赵六就出现了,为什么?什么原理?姓名字段来自一端表:学生表,学生表中的姓名是学校全部的学生名单,赵六和邓七虽然没捐款,但是他们也是这个学校的学生,把他们捐款看成是0元,占比是0%,现在矩阵中显示的是每个人占学校总捐款金额的比例。
总结:当ALL(表名)的时候,无论是内部筛选器还是外部筛选器,都被清除了。写固定值时,我们清除了筛选,所以它显示永远120。外部筛选器,例如我们使用切片器,无论你使用多端表中的日期或班级,还是一端表中的姓名,固定值120是永远不会变的。如图1-8-9


ALL(表)并不是万能的,例如现在这个问题:
为了更好的体现数据,我们将矩阵中行标题改成多端表中的【性别】字段,如图1-8-10

如果你想分析,每个班男生和女生各占全校总捐款金额的占比,就这么写没问题!
但是,如果你想分析,每个班男生和女生各占本班总捐款金额的占比,这么写就不对了,因为一班和二班总捐款金额各60元。现在由于我们使用的是ALL(表),它返回一个固定的120不变。达不到我们的要求。
现在我们将度量值修改:
固定值 = CALCULATE([总捐款],all('捐款表'[性别]))
作用:只对【性别】取消筛选:如图1-8-11

现在固定值仍然显示120,没错!因为我们使用了all('捐款表'[性别]),行标题是性别筛选度量值时,等同于ALL(表)返回一个固定值。
但是,当我们将行标题换成【班级】时:如图1-8-12

当你将行标题换成除了捐款表'[性别]以外任何字段时,固定值都是可以筛选的。因为我们只是all('捐款表'[性别]),并没有ALL整张表,只是性别这一个列清除了筛选,其它列可以正常筛选。
也就是说ALL(列)时,只是那一列相当于是ALL(表)的效果,返回固定值,其它列在筛选时,等同于【总捐款】那个度量值,带有筛选功能。

以上说的是内部筛选器,接下来我们说外部筛选器:
固定值 = CALCULATE([总捐款],all('捐款表'[性别]))
固定值如上所示,我们使用性别做行标题,固定值永久返回120

但是,当我们使用班级做切片器时,它可以让固定值实现筛选功能,因为我们的固定值只是all('捐款表'[性别]),如下图

但是,当我们将行标题换成班级、切片器换成性别时
这是一道数学题:全校只有2个班捐款总计120元,一班和二班各捐款60元。因为我们使用的是all('捐款表'[性别]),所以班级做行标题可以筛选固定值,每个班60元,但是外部切片器性别,就不能筛选固定值,因为是all('捐款表'[性别])。

现在就验证了《火力全开》笔记第7课那句总结:
当ALL参数为列时,忽略该列筛选,
但是,其它字段或外部筛选对其产生作用
这句话是语文知识:其它字段或外部筛选。先读前2个字,再读后7个字。因为这句话,牵扯语文阅读理解,ALL(列)也非常灵活,不易理解,不怪你们。

但是,接下来这就真的不应该了
《火力全开》做了这样一个总结:
注意:ALL函数在引用列的时候,必需与矩阵的行和列在同一张表
假设:
固定值 = CALCULATE([总捐款],all('捐款表'[学号]))
我使用捐款表中的学号做行标题,现在固定值是120,这个你理解。

现在,我将学生表中的学号做行标题,固定值变了,不再是120了

为什么?这是什么原理?哪有什么原理呀?
固定值 = CALCULATE([总捐款],all('捐款表'[学号]))
ALL函数的参数中是哪个表哪个列,不是用中文写的吗?你用其它表中的同名列,肯定无效呀。我现在举一个行标题的例子就足够了。

我在《火力全开》中,分别用两句话解释ALL(表)与ALL(列)
你们为何一定要绕自己?
ALL(表) 不管用什么筛选都返回一个固定值
ALL(列) 只有用这个列筛选才返回一个固定值,其它列筛选都返回可以筛选的值,这时等效于计算器中的度量值。
就这么简单的一个事,不要往复杂里搞!

回归正题,现在我们只写了一列
你可以写多列 All(表名[列名1],表名[列名2],表名[列名3],…….)
假设有100个列,你想在ALL里面写99个列,这样显然不方便,我们使用另一个函数
Allexcept函数:除…之外
语法:Allexcept(表名,表名[列名])
等同于 All(表名[列名1],表名[列名2],表名[列名3],…….)

网友问:我应该什么时候用ALL(表)?什么时候用ALL(列)?
答:需要用ALL(表)时用ALL(表),需要用ALL(列)时用ALL(列),这个由你的业务决定,看你要做什么样的分析。
关于ALL函数与Calculate函数配合使用的详细讲解,
我会安排在《DAX神功》第1卷末来讲,
现在您需要知道ALL函数是怎么回事
关于它的具体用法不用着急,我们慢慢来
