PowerBI之DAX神功:第1卷第21回 Calculate调节器USERELATIONSHIP函数

无忌哥哥永远不可能与黄衫女在一起,他们之间不会建立关系
但是,无忌哥哥与芷若妹妹和敏敏之间有着说不清的关系。
不过,当无忌哥哥跟芷若暧昧时,敏敏肯定不在;反之,与敏敏暧昧时,芷若也不在。
实线是:现任关系
虚线是:备胎关系
所以,无忌哥哥被称作渣男,他并没有违法;如果两条都是实线,那就违了49年以后的法了。
但是,无忌哥哥很聪明,他在虚虚实实中不停的变幻,这种事,就是放在今天,也只能封杀他,撤了他明教教主的职务,抓不了他。(前提他必须是知名人士,如果是江湖中人,也只能道德谴责他)

无忌哥哥是通过什么方法,将虚线关系启用,同时实线关系自动变成虚线?
一、USERELATIONSHIP函数
张无忌是Calculate,USERELATIONSHIP函数是调节器,它不返回任何值,它的作用是开启指定关系并停之原来的关系。
这个函数《孙兴华讲PowerBI火力全开》笔记28.04中详细讲解过,而且还举了两个案例,我们今天不是来炫案例的,这是原理课,我们只讲原理:(案例请看《火力全开》)


需求1:我想使用一端表的日期筛选入职人数
入职人数1= count('多端表'[姓名])
入职人数2= countrows('多端表')
入职人数3=count('多端表'[入职])
以上3个度量值都可以实现入职人数的筛选(功能相同)

需求2:我想使用一端表的日期筛选离职人数
这时,您需要先切换两张表的连线关系

离职人数1= count('多端表'[姓名])
离职人数2= countrows('多端表')
离职人数3=count('多端表'[入职])
以上3个度量值都可以实现相同功能,但是你在做汇报时,你不能在表上改关系玩呀?
这时,我们可以建立一条实线关系,再建立一条虚线关系:

写两个度量值:
入职人数 = count('多端表'[姓名])
离职人数 = CALCULATE([入职人数],USERELATIONSHIP('一端表'[日期],'多端表'[离职]))
新建一张表:方法源于《DAX神功》第1卷第3回
参数表 =
VAR tb =
{
("入职"),
("离职")
}
Return
SelectColumns(tb , "项目" , [Value])
再写一个度量值:
切换 =
switch(TRUE(),
SELECTEDVALUE('参数表'[项目])="入职",[入职人数],
SELECTEDVALUE('参数表'[项目])="离职",[离职人数]
)

的确很方便,但是你要注意一些问题:
【1】两表之间可以有多条线,但只能有一条实线。
【2】你要保证两表是一对多关系
【3】在使用USERELATIONSHIP函数前,必须保证虚线关系已经建立。
我们假设你没有建立虚线关系,就使用USERELATIONSHIP函数会出现下面的情况:
入职人数 = count('多端表'[姓名])
离职人数 = CALCULATE([入职人数],USERELATIONSHIP('一端表'[日期],'多端表'[离职]))


【4】USERELATIONSHIP函数里面两个参数没有顺序,先写谁都可以,总之一个是主键另一个是外键,下面两个度量值都是正确的
离职人数 = CALCULATE([入职人数],USERELATIONSHIP('一端表'[日期],'多端表'[离职]))
离职人数 = CALCULATE([入职人数],USERELATIONSHIP('多端表'[离职],'一端表'[日期]))
【5】Calculate嵌套使用时,只有最内层USERELATIONSHIP函数生效
度量值=
Calculate(
Calculate([总数量],USERELATIONSHIP(主键,外键)),
USERELATIONSHIP(主键,外键)
)
《DAX神功第1卷第18回》讲到DAX所有函数都是从内向外,USERELATIONSHIP函数在calculate中使用只生效第1次
我们举个通俗的例子:
度量值=
Calculate(
Calculate([孩子],USERELATIONSHIP(张无忌,赵敏)),
USERELATIONSHIP(张无忌,周芷若)
)
张无忌和赵敏的孩子,永远都是他们俩的,变不成张无忌和周芷若的孩子

我们应用到自己的案例上来:
总人数 = count('多端表'[姓名])
离职数 =
Calculate(
Calculate([总人数],USERELATIONSHIP('多端表'[离职],'一端表'[日期])),
USERELATIONSHIP('多端表'[入职],'一端表'[日期])
)

离职数2= Calculate([总人数],USERELATIONSHIP('多端表'[离职],'一端表'[日期])

你将度量值【离职数2】嵌套进来,也是一个道理,谁和谁的孩子,DNA是改不了的。
入职数2=Calculate([离职数2],USERELATIONSHIP('多端表'[入职],'一端表'[日期]))
入职数2仍然是离职数2

【6】有人问calculate中可以嵌套多少个USERELATIONSHIP函数?
只有最内层的生效,外面的又不生效,你嵌套他做什么?
【7】USERELATIONSHIP函数不支持新建列?谁说的?
【度量值】总人数=count('多端表'[姓名])
在一端表上新建列没有问题:
新建列 = Calculate([总人数],USERELATIONSHIP('多端表'[离职],'一端表'[日期]))

但是在多端表中新建列就不行了
新建列=Calculate([总人数],USERELATIONSHIP('多端表'[离职],'一端表'[日期]))

先写成度量值再放到新建列上,也不行
度量值 = Calculate([总人数],USERELATIONSHIP('多端表'[离职],'一端表'[日期]))



我们耐心的从头开始分析:
<1> 关系 :日期~入职

新建列建立在一端表中:一端表筛选多端表:

新建列建立在多端表中:

<2> 关系 :日期~离职

一端表:

多端表:

<3> 两条关系

这次我先看多端表上新建列:
多端表,启用虚线关系,禁用实现关系

注意:Calculate是先建立关系,再应用于筛选器。
因为Calculate是先执行调节器USERELATIONSHIP函数,后执行筛选器
原来实线关系是先存在的,现在你现改的关系,所以要先执行调节器USERELATIONSHIP('多端表'[离职],'一端表'[日期])
再应用到筛选器
你重新建立一对多关系后,一端表中的列就被Vlookup到多端表了。


虽然,在我的案例中,1端表只有日期列,但是你看不到的并不是不存在,你始终要记住
一对多关系,就是一端表中所有列Vlookup到多端表中了。
这个时候你就要指定可以筛选的列,禁用Vlookup过来的那些列
列 = Calculate([总人数],USERELATIONSHIP('多端表'[离职],'一端表'[日期]),ALLEXCEPT('多端表','多端表'[姓名],'多端表'[入职],'多端表'[离职]))
//只有指定的列可以筛选,其它列不能筛选

反之,我在一端表中新建列就没这个问题,因为一端筛选多端,不会从多端获取内容

二、名词名句解释
《The Definitive Guide to DAX》中提到的 USERELATIONSHIP函数在激活关系时,关系的定义发生在引用表时,而不是发生在调用Related或其它关系函数时。
这句话翻译成通俗的解释:关系函数只能用在创建行上下文的函数中(例如迭代函数)
calculate和calculatetable 创建是筛选上下文,不能直接使用关系函数

三、筛选器与调节器的顺序

度量值1 = CALCULATE([总分],'Sheet1'[班级]="一班",'Sheet1'[姓名]="二班")
等价
度量值1 = CALCULATE([总分],'Sheet1'[班级]="一班" && 'Sheet1'[姓名]="二班")
解释: 这么写是没有结果的
正确的写法:
度量值1 = CALCULATE([总分],'Sheet1'[班级] in {"一班","二班"})
这样看不出顺序来,我们换成or的关系就看出来了,筛选器是自左向右的先后顺序
度量值2 = CALCULATE([总分],'Sheet1'[班级]="二班" || 'Sheet1'[班级]="一班")
度量值3 = CALCULATE([总分],'Sheet1'[班级]="三班" || 'Sheet1'[班级]="二班")
解释:筛选器从左向右
例如度量值2,找到2班就不会再找1班了,返回2班的分数
例如度量值3,找不到3班,但是能找到2班的,返回2班的分数
但是不同列筛选时,这个顺序对结果是无所谓的,但是仍然从左向右,例如:
度量值4 = CALCULATE([总分],'Sheet1'[班级]="一班" && 'Sheet1'[性别]="男")
《DAX》神功中我们讲解了两个调节器ALL和Keepfilters
ALL即可以是调节器,又可以是表函数
例如:all出现在例如迭代函数第一参数为表的时候,它是表函数
Filter(all(表[列]),筛选条件)
但是,放到calculate筛选器中时ALL系列函数的作用是Calculate调节器。
调节器优先于筛选器
度量值5 = CALCULATE([总金额],ALL('多端表'[姓名]),VALUES('多端表'[姓名]))
度量值6 = CALCULATE([总金额],VALUES('多端表'[姓名]),ALL('多端表'[姓名]))
解释:度量值5和度量值6,结果相同
步骤1:ALL调节器
步骤2:Values筛选器
《DAX神功第1卷第17回》Values做筛选器,它即是表函数又是筛选器,当它放到Calculate筛选器中,它就是筛选器
keepfilters也是调节器,可它不是Calculate的调节器,它是筛选参数调节器,它的作用是:恢复参数的筛选。
网友提问:关于度量值5计值顺序是怎样的?
度量值5 = calculate([销售额], all(日期表), values(日期表[月份]), all(商品表), keepfilters(商品表[商品种类]="A"))
顺序,从左向右,先Calculate调节器,再筛选器:
第1步:all(日期表)
第2步:all(商品表)
第3步:values(日期表[月份])
第4步:keepfilters(商品表[商品种类]="A") //让不能实现筛选的筛选器恢复筛选功能
小常识:
Calculate调节器有哪些?
Userlationship、Crossfilter、ALL、Allselected、Allexcept、Allcrossfiltered、Allnoblankrow
