打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
PowerBI之DAX神功:第1卷第20回 循环依赖什么鬼?

一、循环依赖之时间旅行者

循环依赖是鬼,它活着的时候叫循环引用。

《大话西游大圣娶妻》紫霞仙子说了几句牛魔王听不懂的话:),牛魔王对青霞说:“你妹妹疯了,说了一晚上鬼话!”

大家要知道,循环依赖和循环引用,是一回事,只是活着和死了叫法不一样

【新建列】儿子 = 'Sheet2'[父]+'Sheet2'[母] 

【新建列】孙子 = 'Sheet2'[儿子]+'Sheet2'[儿媳] 

我再修改【儿子】列时,就提示检测到循环依赖

儿子 = 'Sheet2'[父]+'Sheet2'[孙子]

这样造成的循环依赖的原因,大家都清楚:

儿子的出生与孙子无关,没有儿子哪来的孙子?

孙子列是依赖儿子列生成的,你再又让儿子列依赖孙子列生成,是不行的。

二、第二次使用Calculate新建列造成的循环引用

【新建列】销售金额 = sumx('Sheet3','Sheet3'[销量]*'Sheet3'[售价])

新建列(销售金额)是行上下文没有筛选功能,这个表中任何列都不能筛选它

【新建列】销售金额 = calculate(sumx('Sheet3','Sheet3'[销量]*'Sheet3'[售价]))

当套上Calculate之后,所有字段都可以筛选了

当我写第2个新建列时

销售成本 = sumx('Sheet3','Sheet3'[销量]*'Sheet3'[进价])

这样写,哪个列都不能筛选,没问题。但是,我给它也套上一个Calculate时,出问题了:

销售成本 = CALCULATE(sumx('Sheet3','Sheet3'[销量]*'Sheet3'[进价]))

《The Definitive Guide to DAX》中的解释非常专业,也许你能看懂,但是你不可能每次都将他展开找原因。

DAX神功解释:得语文者得天下,得阅读者得语文

这句话已经说得很清楚了,销售成本这列,不能被销售金额这个列筛选

你写成下面这样,取消销售金额这个列的筛选就可以了。

销售成本 = CALCULATE(sumx('Sheet3','Sheet3'[销量]*'Sheet3'[进价]),all(Sheet3[销售金额]))

sumx本来是行上下文,你通过calculate强行转化为筛选上下文

被强行转化的这两列分别是:销售金额和销售成本

销售金额通过前4列筛选:商品、销量、售价、进价

销售成本 = CALCULATE(sumx('Sheet3','Sheet3'[销量]*'Sheet3'[进价]))

这样写出来的销售成本,原则上按前5列筛选:商品、销量、售价、进价、销售金额

销售金额依赖前4列筛选,它就不能再去筛选销售成本,所以要取消销售金额的筛选

首先,筛选器不能重复

其次,筛选器不能隔山打牛

所以,这样写也是错的,因为隔山打牛

销售成本 = CALCULATE(sumx('Sheet3','Sheet3'[销量]*'Sheet3'[进价]),ALL('Sheet3'[商品],Sheet3[销量],Sheet3[售价],Sheet3[进价]))

上面的公式,相当于取消了前4列的筛选,使用销售金额筛选,这样隔山打牛是不行的。

三、多表循环依赖的处理方法

现在这两张表无法建立关系,没有主键和外键

【度量值】总分1 = SUM('成绩表'[分数])

【新建列】等级1 = SWITCH(TRUE(),[总分1]>90,"S",[总分1]>60,"A","B")

【新建列】新列 = [等级1]&"-MG"

怎么解决?因为现在只有一张表,按照单张表处理方法,修改度量值:

【度量值】总分1 = CALCULATE(SUM('成绩表'[分数]),ALL('成绩表'[新列]))

现在我们将【总分1】度量值恢复,并且删除【新列】

【度量值】总分1 = SUM('成绩表'[分数])

两表连线会出现循环引用:

DAX神功完整解释:如果使用成绩表[等级1]与评价表[等级]连线,由于【总分1】这个度量值的上下文作用,成绩表[等级1]就会与评价表[等级]产生依赖关系,而评价表[等级]又通过成绩表和评价表直接的关联关系与成绩表[等级1]产生依赖,这就形成了一个循环依赖关系,所以这两个表不能使用等级字段创建关系。

我担心你看不懂这段话,所以我画个图:

当一端表和多端表建立连线关系后,其实表格是这样的:

就相当于是,1端表中的所有列都Vlookup到了多端表中去了。

现在修改度量值,你只写all(等级1)是不行的,因为连线后,评价表字段也牵连进来了,

【度量值】总分1 = CALCULATE(SUM('成绩表'[分数]),ALL('成绩表'[等级1]))

可是两个表没建立关系之前,你的度量值里无法引用其它表中的列,这时ALLexcept就有了它无法替代的作用

总分1 = CALCULATE(SUM('成绩表'[分数]),ALLEXCEPT('成绩表','成绩表'[学号],'成绩表'[科目],'成绩表'[分数]))

只允许学号,科目,分数列筛选,取消其它所有列的筛选。

有些人会说,不对呀,写成这样也可以

总分1 = CALCULATE(SUM('成绩表'[分数]),ALLEXCEPT('成绩表','成绩表'[学号]))

写成什么样是根据你的业务需求决定的,但是,循环依赖这个鬼,你必须保证    成绩表中的等级1和评价表里所有列在【总分1】度量值中取消筛选

关于其它列是否筛选,由你自己决定。

四、九叔重现,避开鬼打墙,多表循环依赖的处理方法:

这次看每个人数学和语文的总分数+花名册中的加分后得到的每个人总分

大于等于180是S, 大于等于120是A,否则是B

我们在《DAX神功》第1卷第14回 讲过,写法不止下面一种

[新建列]

总分 = 

    var x = '成绩表'[学号]

    return

        sumx(FILTER('成绩表','成绩表'[学号]=x),'成绩表'[分数]+RELATED('花名册'[加分])) 

新建列浪费内存,我们一般会使用度量值方式。

[度量值]

总分 = 

    var x = SELECTEDVALUE('成绩表'[学号])

    return

        sumx(FILTER(all('成绩表'),'成绩表'[学号]=x),'成绩表'[分数]+RELATED('花名册'[加分])) 

[新建列]

等级 = SWITCH(TRUE(),[总分]>=180,"S",[总分]>=120,"A","B")

现在评价表与成绩表通过等级连线就不会出现循环依赖的问题了,当前行概念就是九叔,避开鬼打墙。

五、度量值出现循环引用的概率低

表名:Sheet4

表格白底黑字是网友留言中叙述的原始表,绿底黑字是我在Excel中计算的结果

将白底黑字表格放到PowerBI中,写如下度量值:

本月平均单价 = DIVIDE(sumx('Sheet4','Sheet4'[上月末金额]+'Sheet4'[本月入库金额]),sumx('Sheet4','Sheet4'[月初数量]+'Sheet4'[本月入库数量]))

本月出库金额 = sum(Sheet4[出库数量])*[本月平均单价]

下月初金额 = SUM(Sheet4[上月末金额])+sum(Sheet4[本月入库金额])-[本月出库金额] 

完全正常没有问题。度量值是不易出现循环引用的,也不是绝对,比如讲时间智能日期函数时就会遇到。

建议:

度量值1和5完全没有必要写,心里明白就可以了

打个比方,公司集体会议,无论什么职务,开会点名都答“到”!

我叫孙兴华,是公司的副总裁,同时也是总经理。

你喊我孙兴华,我答“到”!就可以了!叫我一次就可以了,不能因为我有两个职务,你就喊我两次。

如果你喊副总裁,很有可能是总裁答“到”!总裁有可能姓付。

不做无意义的重复劳动。

关于度量值中的循环引用,我们后期课程中还会涉及,敬请期待。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
Power BI之DAX神功:第2卷第6回 让RankX的第3参数不再神秘
Power BI财务应用:应收账款账龄分析
如何在不同工作表中统计各班前40名总分和平均分
PowerBI 零售店铺月度提成四级计算模型
12 如何使用Evaluate做Excel数据查询?
DAX之条件求和
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服