上一篇发现总计行并不是关键点,并根据观察到的现象猜测了3个关键点,本篇通过单变量控制实验逐一对其进行验证,判断哪些条件会触发计算结果与 DAX 理论不符的情况,并最终确认了这些条件。
SUMMARIZECOLUMNS 的疑似 bug(1)引言
SUMMARIZECOLUMNS 的疑似 bug(2)SUMX 在总计行
SUMMARIZECOLUMNS 的疑似 bug(3)总计行是否关键点
SUMMARIZECOLUMNS 的疑似 bug(4)验证触发条件
SUMMARIZECOLUMNS 的疑似 bug(5)最终结论
3 个要验证的条件是:
<groupby>
参数上包含 [关键列]<filter>
参数使用的固化筛选器中包含有 1# 中的 [关键列]- 度量值中存在对 1# 中的 [关键列] 进行迭代的迭代器
【关键列】 是指在 <groupby>
参数中、<filter>
的固化筛选器中、度量值的迭代器中都出现的共同列。
<groupby>
参数指直接对列进行引用的参数,是SUMMARIZECOLUMNS
中放在最靠前的1个或多个列。
<filter>
参数是指可以对表进行筛选的表达式(包括TREATAS
语句),放在SUMMARIZECOLUMNS
的 参数 和值列之间。
1 实验设计思路
按照唯一变量原则,从 3 个条件中保持 2 个条件不变,修改另 1 个条件,观察计算结果是否与 DAX 理论相符。
通过前几篇的实验已经发现,当3种条件都同时满足时,计算结果不符合理论预期,记录在下表中 实验1 这行:
实验 | 条件1 | 条件2 | 条件3 | 结果 |
---|---|---|---|---|
1 | 满足 | 满足 | 满足 | 计算结果不符合预期 |
2 | 不满足 | 满足 | 满足 | ? |
3 | 满足 | 不满足 | 满足 | ? |
4 | 满足 | 满足 | 不满足 | ? |
设计3个实验,使单个条件不满足,观察计算结果。
2 实验2
满足条件2、3,不满足条件1,即 <groupby>
参数不包含【关键列】
2.1 不使用<groupby>
参数的情况
2.1.1 检验方案
从 SUMMARIZECOLUMNS
的 <groupby>
参数中删除 Dates[Year]
EVALUATE
SUMMARIZECOLUMNS (
// Dates[Year], // 去掉此行
TREATAS (
{ ( 2019, 1 ), ( 2019, 2 ), ( 2020, 11 ), ( 2020, 12 ) },
'Dates'[Year],
'Dates'[Month Num]
),
"total", [SumxBug]
)
2.1.2 理论结果
按照 DAX 理论,结果应为 100
2.1.3 实验结果
实验结果得到 100,与 DAX 理论预测结果一致
2.2 有<groupby>
参数但不含关键列的情况
2.2.1 检验方案
修改 SUMMARIZECOLUMNS
的 <groupby>
参数, Dates[Year]
修改为 Dates[Month]
,<filter>
和 度量值中都不含 Dates[Month]
EVALUATE
SUMMARIZECOLUMNS (
Dates[Month], // 修改此处
TREATAS (
{ ( 2019, 1 ), ( 2019, 2 ), ( 2020, 11 ), ( 2020, 12 ) },
'Dates'[Year],
'Dates'[Month Num]
),
"Total", [SumxBug]
)
2.2.2 理论结果
受 TREATAS 影响,行标题有 Jan、Feb、Nov、Dec,分析 [Month] = Nov 这行,理论预测结果 23
2.2.3 实验结果
运行结果在 Nov 这行得到 23,符合理论预测结果
2.3 小结
<groupby>
参数不包含【关键列】时,计算结果符合理论
实验 | 条件1 | 条件2 | 条件3 | 结果 |
---|---|---|---|---|
1 | 满足 | 满足 | 满足 | 计算结果不符合预期 |
2 | 不满足 | 满足 | 满足 | 计算结果符合预期 |
3 | 满足 | 不满足 | 满足 | ? |
4 | 满足 | 满足 | 不满足 | ? |
3 实验3
满足条件1、3,不满足条件2,使<filter>
参数使用的固化筛选器不包含【关键列】
3.1 不存在固化筛选器的情况
3.1.1 验证方案1
从 TREATAS
中去掉与 Dates[Year] 相关的项目,只保留 Dates[Month Num],如此便使固化筛选器不复存在
EVALUATE
SUMMARIZECOLUMNS (
Dates[Year],
TREATAS ( { 1, 2, 11, 12 }, 'Dates'[Month Num] ),
"SumxBug", [SumxBug]
)
3.1.1.2 理论结果
TREATAS
作用下,行标题有 2019 和 2020,分析 Year = 2019 处的计算得 26
3.1.1.3 实验结果
2019年计算得 26,符合理论结果
3.1.2 验证方案1
将TREATAS
构建的固化筛选器拆开成两个 TREATAS
,使得固化筛选器消失
EVALUATE
SUMMARIZECOLUMNS (
Dates[Year],
TREATAS ( { 2019, 2020 }, 'Dates'[Year] ),
TREATAS ( { 1, 2, 11, 12 }, 'Dates'[Month Num] ),
"SumAmount", [SumxBug]
)
3.1.2.1 理论结果
行标题有 2019 和 2020,分析 Year = 2019 这行的计算结果为 26
3.1.2.2 实验结果
实际得到 26,符合理论
3.2 存在固化筛选器但不包含【关键列】的情况
3.2.1 验证方案
修改 TREATAS
部分,删除 Dates[Year]
,保留 Dates[Month Num]
,并增加 Dates[Month]
,使固化筛选器仍然存在。
EVALUATE
SUMMARIZECOLUMNS (
Dates[Year],
TREATAS (
{ ( "Jan", 1 ), ( "Feb", 2 ), ( "Nov", 11 ), ( "Dec", 12 ) },
Dates[Month],
Dates[Month Num]
),
"SumxBug", [SumxBug]
)
3.2.2 理论结果
在 TREATAS
作用下,行标题有 2019年 2020年,分析 2019年 的计算,预测结果为 26
3.2.3 实验结果
实验结果 2019年计算结果为 26,符合理论预测
3.3 小结
<filter>
参数使用的固化筛选器不包含【关键列】时,计算结果符合理论
实验 | 条件1 | 条件2 | 条件3 | 结果 |
---|---|---|---|---|
1 | 满足 | 满足 | 满足 | 计算结果不符合预期 |
2 | 不满足 | 满足 | 满足 | 计算结果符合预期 |
3 | 满足 | 不满足 | 满足 | 计算结果符合预期 |
4 | 满足 | 满足 | 不满足 | ? |
4 实验4
满足条件1、2,不满足条件3,使度量值的迭代器不包含【关键列】
4.1 不含迭代器的情况
4.1.1 验证方案
修改代码,不使用 [SumxBug]
,改用 [SumAmount]
,它的计算内容是 SUM(DFact[Amount])
EVALUATE
SUMMARIZECOLUMNS (
Dates[Year],
TREATAS (
{ ( 2019, 1 ), ( 2019, 2 ), ( 2020, 11 ), ( 2020, 12 ) },
'Dates'[Year],
'Dates'[Month Num]
),
"SumAmount", [SumAmount]
)
4.1.2 理论结果
这是最基础的用法,理论分析部分略过,结果为 2019年计算 2019年1、2月 Amount 之和得 3,2020年计算 2020年11、12月 Amount 之和,得 47
4.1.3 实验结果
实验结果与理论结果一致
4.2 有迭代器但不包含关键列的情况
不包含关键列,即迭代对象不能是<groupby>
和<filter>
固化筛选器中中的列。
考虑到先前的迭代对象 Dates[Year] 与 Dates[Month Num] 是多对1关系,根据这一特征,设计2个更改选项:
- 修改为 Dates[YM]。每个 YM 对应一个 [Year] 和一个[Month Num],
- 修改为 Dates[Month]。每个 Month 对应多个 [Year] 和一个 [Month Num]
4.2.1 验证方案1
迭代对象修改为 Dates[YM],它没有出现在<filter>
参数的固化筛选器中,也没有出现在<groupby>
参数中,它在数据表中与 [Year] 和 [Month Num] 的关系是
[YM](1)–(1)[Year], [YM](1)–(1)[Month Num]
EVALUATE
SUMMARIZECOLUMNS (
Dates[Year],
TREATAS (
{ ( 2019, 1 ), ( 2019, 2 ), ( 2020, 11 ), ( 2020, 12 ) },
'Dates'[Year],
'Dates'[Month Num]
),
"total", SUMX ( VALUES ( Dates[YM] ), [SumAmount] )
)
4.2.1.1 理论结果
TREATAS
作用下行标题包括 2019年和2020年,分析 2019年 的计算结果为3
4.2.1.2 实验结果
与理论结果一致
4.2.2 验证方案2
迭代对象修改为 Dates[Month],它没有出现在<filter>
参数的固化筛选器和<groupby>
参数中,与 [Year] 和 [Month Num] 的关系是
[Month](1)–(*)[Year], [Month](1)–(1)[Month Num]
EVALUATE
SUMMARIZECOLUMNS (
Dates[Year],
TREATAS (
{ ( 2019, 1 ), ( 2019, 2 ), ( 2020, 11 ), ( 2020, 12 ) },
'Dates'[Year],
'Dates'[Month Num]
),
"total", SUMX ( VALUES ( Dates[Month] ), [SumAmount] )
)
4.2.2.1 理论结果
TREATAS
作用下,行标题包含 2019年 和 2020年,分析 2019年的计算结果应为 3
4.2.2.2 实验结果
实际计算 2019年计算出的结果为 3,与理论结果相符。
4.3 有迭代器但包含<filter>
固化筛选器列的情况
4.3.1 迭代对象包含在 <filter>
固化筛选器中,且与 <groupby>
参数列是1对多关系
把迭代器修改为 Dates[Month Num],它也出现在 <filter>
参数的 TREATAS 构建的固化筛选器中,且与 Dates[Year] 的关系是 1对多。
EVALUATE
SUMMARIZECOLUMNS (
Dates[Year],
TREATAS (
{ ( 2019, 1 ), ( 2019, 2 ), ( 2020, 11 ), ( 2020, 12 ) },
'Dates'[Year],
'Dates'[Month Num]
),
"total", SUMX ( VALUES ( Dates[Month Num] ), [SumAmount] )
)
4.3.1.2 理论结果
TREATAS
作用下,行标题有 2019 和 2020,分析 2019年的计算得 3
4.3.1.3 实验结果
2019 年得到 3,与理论相符
4.3.2 迭代对象包含在 <filter>
固化筛选器中,且与 <groupby>
参数列是1对1关系
为了验证该情况,需要修改数据表,增加一个与 Year 列1对1关系的列,比如将 Year 列复制到 YearD 列,Year 与 YearD 是1对1的关系。
修改代码,将<groupby>
参数修改为Dates[YearD]
,如下所示,现在<filter>
固化筛选器和度量值迭代对象都包含有 Dates[Year]
,且与参数列的 Dates[Year]
是 1对1 关系
EVALUATE
SUMMARIZECOLUMNS (
Dates[YearD],
TREATAS (
{ ( 2019, 1 ), ( 2019, 2 ), ( 2020, 11 ), ( 2020, 12 ) },
'Dates'[Year],
'Dates'[Month Num]
),
"total", SUMX ( VALUES ( Dates[Year] ), [SumAmount] )
)
4.3.2.1 理论结果
在 TREATAS
作用下,行标题的 Year2 包含有 2019 和 2020,分析 2019 这一行的计算结果为 26
4.3.2.2 实验结果
2019年计算得到3,与理论相符
4.4 小结
满足条件1、2,不满足条件3,度量值的迭代器不包含【关键列】,计算结果与理论相符
5 结论分析
综合以上信息,记录到表中
根据观测记录形成最终结论,当同时满足如下条件时,SUMMARIZECOLUMNS
的计算结果与理论不符
<filter>
参数中有固化筛选器<groupby>
参数中有<filter>
固化筛选器中的列,且计算发生在该列的粒度上- 计算值使用迭代器,迭代对象同时出现在
<filter>
参数和<groupby>
参数中
综上所述,我们找到了 SUMMARIZECOLUMNS
触非疑似 BUG 的充分条件。