ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 4830|回复: 20

[求助] [PowerBI]ALLEXCEPT在扩展表中表现错误

[复制链接]

TA的精华主题

TA的得分主题

发表于 2019-5-18 22:26 | 显示全部楼层 |阅读模式
现有简单模型Data表与其日历,日历由CALENDARAUTO自动生成(并添加自定义列YearMonth),Data形如:

1.png


求:每个Name对应的YearMonth个数。
写法如下:
  1. Wrong =
  2. ADDCOLUMNS (
  3.     VALUES ( Data[Name] ),
  4.     "MonthNum", CALCULATE (
  5.         CALCULATE (
  6.             DISTINCTCOUNT ( 'Date'[YearMonth] ),
  7.             CALCULATETABLE ( ALLEXCEPT ( Data, Data[Name] ) )
  8.         )
  9.     )
  10. )
复制代码

我的理解:外层Calculate将当前Name转换为筛选上下文,内层Calculatetable在Allexcept作用下保留扩展表Data的Name列筛选,同时清除其他列筛选,即最后扩展表Data只有Name列有筛选,又由于Data扩展表包括日历表,因此实现对日历表的筛选,计算预期值。
实际:所有行都是一个值,即全部的YearMonth个数,Name列筛选无效。
同样的思路,改用All可行:


  1. Correct =
  2. ADDCOLUMNS (
  3.     VALUES ( Data[Name] ),
  4.     "MonthNum", CALCULATE (
  5.             DISTINCTCOUNT ( 'Date'[YearMonth] ),
  6.             FILTER ( ALL(Data),Data[Name]=EARLIER(Data[Name]) )
  7.     )
  8. )
复制代码


不能理解,求解答。

pbix附件:
Test.zip (63.06 KB, 下载次数: 31)

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-5-21 14:32 | 显示全部楼层
本帖最后由 shwangfeng 于 2019-5-21 14:33 编辑

原因虽然不晓得,但其实改正的办法非常简单,只要在Calculatetable后面加上原表名就好了:
  1. Wrong =
  2. ADDCOLUMNS (
  3.     VALUES ( Data[Name] ),
  4.     "MonthNum", CALCULATE (
  5.         CALCULATE (
  6.             DISTINCTCOUNT ( 'Date'[YearMonth] ),
  7.             CALCULATETABLE ( Data, ALLEXCEPT ( Data, Data[Name] ) )
  8.         )
  9.     )
  10. )
复制代码


但这也只能从侧面说明Allexcept并非像《DAX圣经》或者dax.guide中说的那样跟All差不多,仍然没有揭示本质原因,即到底它返回的是不是表。
这两种官方参考每次提到Allexcept都只说它可以用扩展表中的任何表或者列作为排除参数,而从来不进一步展示这样做的结果是不是符合他们下的定义,看得我有点窝火。

TA的精华主题

TA的得分主题

发表于 2019-5-21 16:30 | 显示全部楼层
CALCULATETABLE ( ALLEXCEPT ( Data, Data[Name] ),
我感觉是:除了name列,其余列均去除了筛选。这一点是肯定的。
但根据扩展表的概念,data表扩展版本也包含了日期表,因此“其余列”包含了日期表的各个列。日期表的各个列均   “ALL”  了,即不筛选,导致计算的年月个数均是相同的。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-5-21 17:30 | 显示全部楼层
楼上正解,用事实表做筛选条件一定要注意对扩展表的影响,DAX黄金法则之一,能用列做筛选的不要用表做筛选。www.sqlbi.com上对此有专门的讲解,原理跟你这个错误一样。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-5-21 18:07 | 显示全部楼层
zjnfxxh 发表于 2019-5-21 16:30
CALCULATETABLE ( ALLEXCEPT ( Data, Data[Name] ),
我感觉是:除了name列,其余列均去除了筛选。这一点 ...

感谢回答!
我对扩展表的理解也是这样,而且正因为Data的扩展表包含了Date,所以在保留Name筛选的情况下可以计算每个Name对应的非重复YearMonth个数,无论是书上还是网站上都举过相应的例子,没有问题。也就是说,整个扩展表中"只有Name列有筛选"正是计算出正确结果的前提——参考我改正后的版本,是可以返回预期结果的。
要计算出正确结果,大体的计算流程推理如下:
Addcolumns按Name制造行上下文,对于每个迭代到的Name,使用Calculate将当前Name转换为筛选上下文,但因为上下文转换只会作用于Calculate第一参数,而此处Name列属于单列筛选,单列筛选只对包含它的扩展表有效,Date表的扩展表不包含Name,所以这里的转换实际不能对结果产生影响。为了真正激活Name列筛选,必须在Calculate第二参数以后,再构建一个包含Date表的扩展表,即此处的Data表,如果这个Data的扩展表中包含Name列筛选,那么它就能覆盖(因为上下文转换先发生)之前(其实无效的)上下文转换效果,返回预期结果。所以真正的问题在于,如何构建这个符合需要的“既转换并保留Name列筛选,同时清除其他所有筛选”的Data扩展表。

因为仍然要进行上下文转换,并且返回结果需要一个表,所以嵌套了一个Calculatetable,它将Data扩展表作为第一参数,在第二参数中使用Allexcept清除扩展表中其他列的筛选,同时进行上下文转换(因为外层Calculate做的转换并不影响第二及以后的参数,所以此时行上下文还在,可以再被转换)作用于第一参数,这样两部分组合以后就是想要的结果了,最终结果符合预期:
  1. ADDCOLUMNS (
  2.     VALUES ( Data[Name] ),
  3.     "MonthNum", CALCULATE (
  4.             DISTINCTCOUNT ( 'Date'[YearMonth] ),
  5.             CALCULATETABLE ( Data, ALLEXCEPT ( Data, Data[Name] ) )
  6.         )
  7.     )
复制代码


而错误的版本仅仅是删除了其中的Data,部分,此时Allexcept成为第一参数,接受上下文转换,又因为这个转换正好就是Allexcept排除掉的Name列,所以Calculatetable返回的Data扩展表理应和前面正确的算法相同,进而最终结果也相同。

而现在不是,说明Calculatetable并没有返回预期的扩展表,所以问题就在Allexcept上面,它到底返回的是什么?
按道理说Calculatetable处理过的总应该是一个表,难道这个表不是扩展表吗?

我的感觉是Allexcept并不是简单的返回表,一般筛选条件只有单列和整表两种,但Allexcept返回结果既不是单列也不是整表,可能是什么特别的机制——也许它实际返回的是由很多单列组成的组合,而Date扩展表不包含Name列,所以单列筛选再次失败?
而且这样也解释了为什么这个问题只出现在扩展表中,如果是普通的计算(例如同一表内)就没有问题。
只不过我一点证据也没有,而且我也无法理解Calculatetable到底是怎么对待返回值的,毕竟错误版本也是经过它处理的。





TA的精华主题

TA的得分主题

 楼主| 发表于 2019-5-21 18:42 来自手机 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
mathspirt 发表于 2019-5-21 17:30
楼上正解,用事实表做筛选条件一定要注意对扩展表的影响,DAX黄金法则之一,能用列做筛选的不要用表做筛选 ...

我是想知道这个函数的原理,黄金法则我在sqlbi上面也看到过,但我遇到的错误和他们举的例子不同,找不到相关的解释。

TA的精华主题

TA的得分主题

发表于 2019-5-22 00:06 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 张文洲 于 2019-5-22 08:06 编辑
shwangfeng 发表于 2019-5-21 18:42
我是想知道这个函数的原理,黄金法则我在sqlbi上面也看到过,但我遇到的错误和他们举的例子不同,找不到 ...

是个典型的问题,涉及到ALLEXCEPT函数的用法,不过具体原理说起来确实有些复杂

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-5-22 07:59 来自手机 | 显示全部楼层
张文洲 发表于 2019-5-22 00:06
是个典型的问题,涉及到ALLSELECTED函数的用法,不过具体原理说起来确实有些复杂

大佬是说,只有看明白号称最复杂的Allselected和什么shadow context才能彻底搞清楚这个问题咯?可是每一种参考资料提到Allexcept都只是简单地说它是all的小弟,根本没有展开……既然如此,我先去研究一下Allselected看看。谢谢指点。

TA的精华主题

TA的得分主题

发表于 2019-5-22 08:06 | 显示全部楼层
shwangfeng 发表于 2019-5-22 07:59
大佬是说,只有看明白号称最复杂的Allselected和什么shadow context才能彻底搞清楚这个问题咯?可是每一 ...

是ALLEXCEPT,我写错了

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-5-22 09:56 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
张文洲 发表于 2019-5-22 08:06
是ALLEXCEPT,我写错了

我主要就是想知道这个函数的原理,它如何接受外部筛选(包括第一参数以及后面的排除参数),以及它返回的是表还是列,我在五楼写了我的想法,请有空的时候指点其中的错误,感激不尽。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-4-30 23:13 , Processed in 0.048678 second(s), 13 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表