Power BI之DAX神功:第3卷第8回 INTERSECT与EXCEPT函数
《孙兴华讲PowerBI火力全开》我们简单了介绍了一下INTERSECT与EXCEPT函数,今天我们深入讲原理。
一、INTERSECT函数

语法:INTERSECT(左表,右表) // 只支持两张表
a. 返回两张表共有的行,返回结果不去重。
b. 两张表列的位置、列数,数据类型三者都要相同
c. 保留左表数据沿袭
// 数据类型非常重要,详见《DAX神功》第1卷第4回
【1】两个参数位置颠倒会影响数据沿袭
// 表1和表2 无连线关系

【新建表】交叉表1 = INTERSECT('表1','表2')

【新建表】交叉表2 = INTERSECT('表2','表1')

因为参数用的是整张表,所以它会考虑满足条件的所有列。但是你观察他始终返回的是左表所有列。换而言之,当你对两个参数交换位置时,你要想清楚,你要的是谁?可能你会说,两张表字段都一样时,我拿谁不一样呀?还真不一样。我们看一下下面两个新建表
交叉表3 = addcolumns(INTERSECT('表2','表1'),"工资",CALCULATE(SUM('表2'[2月工资])))
// 因为数据沿袭只保留INTERSECT函数左表的列

交叉表4 = addcolumns(INTERSECT('表2','表1'),"工资",CALCULATE(SUM('表1'[1月工资])))

学到这里的小伙伴应该是懂数据沿袭的原理,我就不再重复讲了。以上两表您可以交换addcolumns第3参数,再看看结果就理解,INTERSECT保留左表的数据沿袭。
【2】INTERSECT可以被TREATAS替代
交叉表5 = addcolumns(INTERSECT(VALUES('表2'[name]),VALUES('表1'[姓名])),"工资",CALCULATE(SUM('表2'[2月工资])))
// 保留左表的数据沿袭

交叉表6 = addcolumns(TREATAS(VALUES('表1'[姓名]), '表2'[name]),"工资",CALCULATE(SUM('表2'[2月工资])))
// TREATAS第1参数筛选第2参数,在第2参数上做标记。注意TREATAS与INTERSECT参数位置问题。

二、EXCEPT函数

语法:EXCEPT(左表,右表) // 只支持两张表
a.从左表中除去与右表重合的所有行,返回表不去重
b.两张表列的位置、列数,数据类型三者都要相同
c.保留左表数据沿袭
// 表1和表2无连线关系

【新建表】除去1 = EXCEPT('表1','表2')

【新建表】除去2 = EXCEPT('表2','表1')

【新建表】除去3 = EXCEPT(VALUES('表2'[name]),values('表1'[姓名]))

两个参数位置颠倒会影响数据沿袭:原理与INTERSECT函数相同,都保留左表的数据沿袭,我不再重复举例了
本节课在《The Definitive Guide to DAX》有两个案例值得借鉴:我不能照搬人家案例,也不能照搬人家代码,但是可以写出读后感,供大家看书学习。
(1)例如查询2020年购买过产品但是2021年无购买行为的客户
可以用calculatetable或filter分别筛选2020和2021年的客户表,通过EXCEPT(2020客户表,2021客户表) 这点很重要,因为你要从2020年的表中除去2021年没买过的,顺序不要错。
(2)将上一年购买过产品的客户从当前客户集合中除去。
我们在讲时间智能日期函数时讲过去年同期怎么算?
所有客户 = DISTINCT(客户列) // 拿到所有客户去重后的表,假设不止两年,可以通过Filter或Calculate筛选 年>=20XX 或 日期>Date(20XX,12,31)
去年同期 = filter(所有客户, 使用时间智能计算去年同期日期表) //使用Calculate也可以 ,筛选去年同期满足条件的客户表
EXCEPT(所的客户,去年同期)
三、回答网友问题UNION、INTERSECT、EXCEPT仅筛选自身包含的列
UNION(合并)、INTERSECT(交叉)、EXCEPT(除去)都是返回一张表,但是这张表只能筛选自身包含的列,不能筛选其它列,即便保留了数据沿袭且表与表之间符合筛选关系也不可以筛选。PS:案例本身并无实际意义,只是为了讲清楚筛选问题


上面这个度量值,部分人理解有误,并不是多端表筛选一端表,用多端表中的所有行筛选一个值。《DAX神功》第1卷第8回 已经针对这个问题做出了详细解释。
度量值=Calculate(计算器,筛选器)
// 计算器返回一个值,筛选器筛选这个值。计算器是度量值的一部分,计算器不等于度量值

放到矩阵中的结果,与我们脑子里想的结果是一样的:

从表面上看,通过UNION得到的这张表与多端表是一样的:

但是,我们将这张表写到度量值中,会发现结果不同:

为什么会这样?因为咱们还没有讲到扩展表,所以我避开这个知识来讲


友情提示:下图在手机上观看,可以点击后通过两根手指放大。在电脑上观看时可使用鼠标滚轮放大。原理写在图片上了。


孙兴华讲PowerBI火力全开》PowerBI必学课程
https://www.bilibili.com/video/BV1qa4y1H7wp
《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等等