欢迎光临散文网 会员登陆 & 注册

Power BI之DAX神功:第2卷第21回 数据沿袭和TREATAS函数

2021-11-24 08:28 作者:孙兴华zz  | 我要投稿

数据沿袭我们一直在用,只是你不知道他的概念而已。如果不利用数据沿袭并非不能实现想要的效果,这节课我们就展开讲一下数据沿袭。

一、什么是数据沿袭?

《DAX神功》答网友问05 返回表的迭代函数你应该注意什么?

我向大家证明了:

ADDCOLUMNS相当于整容,例如你长了两只眼睛,整容可以让你变成3只,但你还是你。

SELECTCOLUMNS相当于克隆再整容,克隆你再整容成3只眼,长的一样,但是那不是你。

表名:Sheet1

【新建表】

tb = ADDCOLUMNS(SELECTCOLUMNS('Sheet1',"学生姓名",'Sheet1'[姓名]),"分数",[总分])

// SELECTCOLUMNS克隆Sheet1,新字段名是:学生姓名,取Sheet1表中的姓名列生成新字段,用ADDCOLUMNS在克隆表新字段中添加“分数”列,使用度量值【总分】按人筛选。

友情提示:我的案例Sheet1是一端表,如果是多端表你要考虑姓名去重的问题。将公式中SELECTCOLUMNS的第1参数'Sheet1'替换为Values('Sheet1'[姓名] DISTINCT('Sheet1'[姓名]

《DAX神功》第1卷第9回讲到二者区别:根据自己需求选择使用

Values(表):复制一张表。

Distinct(表):所有列都重复才去重并返回去重后的表。

虽然我在克隆表中新建了字段,但是我给新字段做了一个记号,记号上写着原来的字段是Sheet1[姓名]。我为克隆表中新字段匹配度量值【总分】时,其实度量值是按原字段规则给新字段匹配。

这样说我觉得还是很官方,咱们说个通俗易懂的,我叫孙兴华,我是男的,我通过手术变成了女人,通过合法途径改变了姓名、身份证号码、性别。但是公安机关会在公安系统里做标识,注明了我原身份证号。(如下图所示)

一年之后,某法院受理了一起孙兴华欠他人5万元的案件,借款人叫孙兴华,身份证123。但是现在的孙兴华和身份证号123已经不存在了。法院传票不是发给孙兴华,而是发给貂蝉,通过原身份证号这个标识,找到变成女人之后的孙兴华。--这就是沿袭,也可以叫它延续,血脉相传,叫什么不重要,你开心就好。

多个列之间也可以沿袭:

两张表之间建立关系:

【新建表】tb1 = SELECTCOLUMNS('Sheet3',"姓名新",'Sheet3'[姓名],"科目新",RELATED('Sheet4'[科目]) )

// 从Sheet3表中获取姓名列,从Sheet4表中获取科目列,分别重命名

我们为这张新表分配度量值:

【新建表】tb1 = ADDCOLUMNS(SELECTCOLUMNS('Sheet3',"姓名新",'Sheet3'[姓名],"科目新",RELATED('Sheet4'[科目]) ),"分数",[总分])

在这个基础上还可以使用度量值筛选:

【新建表】tb1 = filter(ADDCOLUMNS(SELECTCOLUMNS('Sheet3',"姓名新",'Sheet3'[姓名],"科目新",RELATED('Sheet4'[科目]) ),"分数",[总分]),[总分]<7 && [总分]>2)

二、什么情况下失去数据沿袭

【1】通过新建表保存的表会失去数据沿袭

孙兴华变成女人后,电脑记录了这一切,但是这只限于我在国内通过合法途径改名、改性别、改身份证号。如果我是偷渡到泰国,做了手术,改了性别,通过泰国的关系上了户口。找我就不容易了。

【新建表】tb1 = ADDCOLUMNS(SELECTCOLUMNS('Sheet3',"姓名新",'Sheet3'[姓名],"科目新",RELATED('Sheet4'[科目]) ),"分数",[总分])

// 当我通过新建表,创建了一张新表时,列上的标记就不存在了。

【新建表】tb2 = FILTER(tb1,[总分]<7 && [总分]>2)

// 这时就没有沿袭了

【2】修改列表达式失去沿袭

例如下图所示,虽然貂蝉记录了原身份证号,但是写错了,也就查不到孙兴华了。

【新建表】tb1 = ADDCOLUMNS(SELECTCOLUMNS('Sheet3',"姓名新","姓名:"&'Sheet3'[姓名],"科目新","科目:"& RELATED('Sheet4'[科目]) ),"分数",[总分])

三、为什么表构造函数不能直接做Calculate的筛选器

有下面两张表,我们不建立关系

【度量值】总分 = sum(Sheet1[分数])

【度量值】筛选 = CALCULATE([总分],'Sheet2')

// Sheet1和Sheet2没有关系,没有关系就没办法筛选,上面的度量值【筛选】返回结果:1+2+3=6 (张三、李四、王五三个人的成绩),就是没进行筛选

表构造函数就是这样的情况:《DAX神功》第1卷第3回 表构造函数

【新建表】表构造函数 = {"张三","李四"}  

// 官方语言管这个叫“匿名表”,我不管你是匿名还是实名,没关系就是没关系

那我问问你,下面这两个公式有什么区别:

【度量值】筛选 = CALCULATE([总分],'Sheet2')

【度量值】筛选表构造函数 = CALCULATE([总分], {"张三","李四"})

// 一样的,都是没有筛选【总分】,为什么没有筛选?因为你没有建立关系

四、如果我想使用表构造函数筛选度量值应该怎么做?

【度量值】筛选张三和李四 = CALCULATE([总分],'Sheet1'[姓名] in {"张三","李四"})

// 因为:总分 = sum(Sheet1[分数])  在本案例上,我想筛选度量值【总分】中张三和李四的分数,那就只能在Sheet1这张表的姓名字段上下手。我需要让表构造函数关联到Sheet1姓名字段。于是我使用了 'Sheet1'[姓名] in {"张三","李四"} Sheet1姓名字段中找出张三和李四

拓展问题:当我们将度量值放到矩阵中会发现,度量值不能被姓名筛选,但是它可以被班级筛选

为什么会出现这样的情况?《DAX神功》第1卷第17回 KEEPFILTERS函数 中我们讲到:

【度量值】筛选张三和李四 = CALCULATE([总分],'Sheet1'[姓名] in {"张三","李四"})

【度量值】等价公式=CALCULATE([总分],filter(all('Sheet1'[姓名]),'Sheet1'[姓名] in {"张三","李四"}))

我在《DAX神功》番外篇 第1回 Calculate+ALL表 与 Filter+ALL表 是两个概念 中对此做出了详尽的解释。

如果我们想实现筛选功能如何处理呢?

【1】Calculate使用Keepfilters恢复指定列的筛选

筛选张三和李四 = CALCULATE([总分],KEEPFILTERS('Sheet1'[姓名] in {"张三","李四"}))

【2】filter中将all改成Values或DISTINCT

等价公式=CALCULATE([总分],filter(DISTINCT('Sheet1'[姓名]),'Sheet1'[姓名] in {"张三","李四"}))

等价公式=CALCULATE([总分],filter(Values('Sheet1'[姓名]),'Sheet1'[姓名] in {"张三","李四"}))

Ps:关于VALUES与DISTINCT函数的区别,详见《DAX神功》第1卷第9回

总结: {"张三","李四"}就是我们说的貂蝉,'Sheet1'[姓名] 就是我们说的孙兴华,意思是{"张三","李四"}来源于'Sheet1'[姓名]中,这就是数据沿袭

五、使用 TREATAS 函数修改数据沿袭

《PowerBI火力全开》第24课  TREATAS 函数

我告诉大家,TREATAS 函数功能是:把第1参数当做第2参数的筛选器,通过一参筛选二参

TREATAS({"张三","李四"},Sheet1[姓名]// 用{"张三","李四"}筛选Sheet1中的姓名列

相当于

'Sheet1'[姓名] in {"张三","李四"}  // 将Sheet1中的姓名列中包含{"张三","李四"}的筛选出来

现在你应该清楚的看到了TREATAS函数的作用,所以我们将公式写成:

【度量值】改变数据沿袭 = CALCULATE([总分],TREATAS({"张三","李四"},Sheet1[姓名]))

这样返回的结果,仍然是姓名列不能筛选,我们还是用Keepfilters处理:

改变数据沿袭 = CALCULATE([总分],keepfilters(TREATAS({"张三","李四"},Sheet1[姓名])))

六、实战练习

我们想看每个会员卡号最后一次消费的金额:

【新建表】

日期表 = ADDCOLUMNS(

CALENDAR(FIRSTDATE('销售表'[日期]),LASTDATE('销售表'[日期])),

"年", YEAR ( [Date] ),

"季度", ROUNDUP(MONTH([Date])/3,0),

"月", MONTH([Date]),

"周", weeknum([Date]),

"年季度", year([date]) & "Q" & ROUNDUP(MONTH([Date])/3,0),

"年月", year([Date]) * 100 + MONTH([Date]),

"年周", year([Date]) * 100 + weeknum([Date]),

"星期几", WEEKDAY([Date])

)

【度量值】总金额 = sum('销售表'[金额]) 

【度量值】最后一次购买的金额 = SUMX ('销售表',CALCULATE ([总金额],'日期表'[Date] = max('销售表'[日期])))

拓展知识:看到最后购买的日期

【度量值】最后一次购买的日期 = SUMX ('销售表',CALCULATE (VALUES('销售表'[日期]),'日期表'[Date] = max('销售表'[日期])))

// VALUES('销售表'[日期])去重后以标题值的方式返回,详见《DAX神功》第1卷第10回

《DAX神功》第1卷第15回 我们证明了以下内容:

SUMMARIZECOLUMNS并不完美,它不支持上下文转换时发生的计算,所以绝大部分度量值中不能使用,如果需要在度量值中执行分组和新建列时用SUMMARIZE+ADDCOLUMNS

我们新建表时可以使用SUMMARIZECOLUMNS,现在需要写度量值,我们改用SUMMARIZE+ADDCOLUMNS的组合:

【度量值】总金额 = sum('销售表'[金额]) 

【度量值】最后一次购买的日期=max('销售表'[日期]) 

【度量值】利用数据沿袭计算最后一次购买金额 = 

VAR tb1 = SUMMARIZE ('销售表','销售表'[会员卡号])

VAR tb2 =ADDCOLUMNS (tb1,"最后一次",[最后一次购买的日期])

return

CALCULATE ([总金额],TREATAS (tb2,'销售表'[会员卡号],'日期表'[Date]))

// TREATAS 中tb2是第1参,'销售表'[会员卡号],'日期表'[Date]是第2参

计算过程:

《孙兴华讲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等等

https://www.bilibili.com/read/cv10222110

Power BI之DAX神功:第2卷第21回 数据沿袭和TREATAS函数的评论 (共 条)

分享到微博请遵守国家法律