SUMMARIZECOLUMNS 的疑似 bug(2)SUMX 在总计行

SUMX引发的思考 SUM,SUMX大概是绝大多数人学习PowerBI时先学的函数,那么我们真的了解它吗? 先来看数据模型 我们可以很容易就写出销售额的度量 销售额 = SUM( 'Sales'[SalesAmount] ) 结果很好理解,比如2020年的总计333565=82140+84122+83992+83311,同样的我们可以求出每季度在售的产品数有多少个 产品数 = DISTINCTCOUNT( 'Sales'[ProductKey] ) 这也没什么问题,那么问题来了,现在领导说在算年度总计时应该是每个季度 阅读详情

SUMX 在 SUMARIZECOLUMNS 总计行的底层计算过程

上一篇介绍了 SUMMARIZECOLUMNS 在特定情况下计算出的结果不符合 DAX 理论预测,这一篇我们开开始探究 DAX 在底层究竟是如何计算出这些结果的,主要的方法是用 DAX 查询复现该现象,通过观察物理查询计划了解底层计算步骤,试图从中定位到问题所在。


SUMMARIZECOLUMNS 的疑似 bug(1)引言
SUMMARIZECOLUMNS 的疑似 bug(2)SUMX 在总计行
SUMMARIZECOLUMNS 的疑似 bug(3)总计行是否关键点
SUMMARIZECOLUMNS 的疑似 bug(4)验证触发条件
SUMMARIZECOLUMNS 的疑似 bug(5)最终结论


现象描述

​![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fassets.b3logfile.com%2Fsiyuan%2F1690605424726%2Fassets%2Fimage-20240523100107-hhhjyfd.png%20%22sumx%20%E5%9C%A8%E6%80%BB%E8%AE%A1%E8%A1%8C%22&pos_id=img-dXDqMRhc-1716550483921)
​

红框处,2019年和2020年总计行的计算结果为:

  • 2019年的总计显示为 30,其计算的是 2019年1月、2019年2月、2020年1月、2020年2月,这4个月的 Amount 之和:1+2+13+14 = 30
  • 2020年的总计显示为 70,其计算的是 2019年11月、2019年12月、2020年11月、2020年12月,这4个月的 Amount 之和:11+12+23+24 = 70。

可以用以下 DAX 查询的结果来类比(并不是说本案例实际是这样执行的):

​image​

底层计算过程

为了弄清楚 PowerBI 在底层是怎么计算出这个结果的,需要我们深入到查询计划中去。首先提炼核心 DAX 查询代码。

PowerBI 在代码层面通过如下 DAX 查询代码计算报表中的矩阵:

DEFINE
	VAR __DS0FilterTable =  // 切片器提供
		TREATAS(
			{(2019, 1),
				(2019, 2),
				(2020, 11),
				(2020, 12)},
			'Dates'[Year],
			'Dates'[Month Num]
		)

	VAR __DS0Core = 
		SUMMARIZECOLUMNS(
			ROLLUPADDISSUBTOTAL(
                'Dates'[Year], "IsGrandTotalRowTotal", // 按年汇总,即 矩阵最下方的总计
                'Dates'[Month Num], "IsDM1Total"),  // 按月汇总,即 年 总计
			__DS0FilterTable,   // 切片器提供的筛选器
			"SumxBug", 'Measure'[SumxBug]
		)

	VAR __DS0PrimaryWindowed = 
		TOPN(
			502,
			__DS0Core,
			[IsGrandTotalRowTotal],
			0,
			'Dates'[Year],
			1,
			[IsDM1Total],
			0,
			'Dates'[Month Num],
			1
		)

EVALUATE
	__DS0PrimaryWindowed

ORDER BY
	[IsGrandTotalRowTotal] DESC, 'Dates'[Year], [IsDM1Total] DESC, 'Dates'[Month Num]

从该代码中将核心部分提出来,保持按月汇总,取消按年汇总(不是本次观察对象),得到如下的实验代码

DAX 查询

用以下 DAX 代码复现 30 和 70 的错误计算结果

EVALUATE
SUMMARIZECOLUMNS (
    'Dates'[Year],
    ROLLUPADDISSUBTOTAL ( 'Dates'[Month Num], "IsDM1Total" ),
    TREATAS (
        { ( 2019, 1 ), ( 2019, 2 ), ( 2020, 11 ), ( 2020, 12 ) },
        'Dates'[Year], 'Dates'[Month Num]
    ),
    "SumxBug", [SumxBug] 
)

运行结果中 [IsDM1Total] 为 True 、Year = 2019 和 Year = 2020 这两行,分别得到 30 和 70,符合报表计算结果。

​image​

存储引擎

Server Timings 界面记录了 4 次 Scan

​image​

存储引擎执行了 4 个 xmSQL 查询,从上往下分别是:

  • VQ1,F2V1
// xmSQL VQ1
SELECT
    'Dates'[Year],
    'Dates'[Month Num],
    SUM ( 'DFact'[Amount] )
FROM 'DFact'
    LEFT OUTER JOIN 'Dates'
        ON 'DFact'[Date]='Dates'[Date]
WHERE
    'Dates'[Month Num] IN ( 12, 1, 2, 11 ) VAND
     ( 'Dates'[Year], 'Dates'[Month Num] ) IN { ( 2020, 12 ) , ( 2019, 2 ) , ( 2020, 11 ) , ( 2019, 1 ) };

从 DFact 的扩展表中,以 Dates[Year]、Dates[Month Num] 分组计算 SUM(DFact[Amount])​,筛选条件为:

1、‘Dates’[Month Num] IN ( 12, 1, 2, 11 )

2、( ‘Dates’[Year], ‘Dates’[Month Num] ) IN { ( 2020, 12 ) , ( 2019, 2 ) , ( 2020, 11 ) , ( 2019, 1 ) }

​image​

  • VQ2,F2V0
// xmSQL VQ2
SELECT
    'Dates'[Year],
    'Dates'[Month Num]
FROM 'Dates'
WHERE
     ( 'Dates'[Year], 'Dates'[Month Num] ) IN { ( 2020, 12 ) , ( 2019, 2 ) , ( 2020, 11 ) , ( 2019, 1 ) };

从 Dates 表中,获取 Dates[Year]、Dates[Month Num] 的不重复值对,筛选条件为:

( ‘Dates’[Year], ‘Dates’[Month Num] ) IN { ( 2020, 12 ) , ( 2019, 2 ) , ( 2020, 11 ) , ( 2019, 1 ) }

​image​

  • VQ3,F1V0
// xmSQL VQ3
SELECT
    'Dates'[Year]
FROM 'Dates'
WHERE
     ( 'Dates'[Year], 'Dates'[Month Num] ) IN { ( 2020, 12 ) , ( 2019, 2 ) , ( 2020, 11 ) , ( 2019, 1 ) };

从 Dates 表中,获取 Dates[Year] 的不重复值,筛选条件与 VQ2 相同

( ‘Dates’[Year], ‘Dates’[Month Num] ) IN { ( 2020, 12 ) , ( 2019, 2 ) , ( 2020, 11 ) , ( 2019, 1 ) }

​image​

  • VQ4,F2V1
SELECT
    'Dates'[Year],
    'Dates'[Month Num],
    SUM ( 'DFact'[Amount] )
FROM 'DFact'
    LEFT OUTER JOIN 'Dates'
        ON 'DFact'[Date]='Dates'[Date]
WHERE
    'Dates'[Year] IN ( 2019, 2020 ) VAND
    'Dates'[Month Num] IN ( 12, 1, 2, 11 ) ;

与 VQ1 非常相似,从 DFact 的扩展表中,以 Dates[Year]、Dates[Month Num] 分组计算 SUM(DFact[Amount])​,筛选条件与 VQ1 有区别:

‘Dates’[Year] IN ( 2019, 2020 )

‘Dates’[Month Num] IN ( 12, 1, 2, 11 )

注意,从 VQ4 的 xmSQL 代码可以看出,WHERE 子句使用的条件,破坏了报表切片器构造的固化筛选器,该查询得到的结果中包含有 2019 年11、12月以及 2020 年1、2月的数据。

​image​

逻辑查询计划

​image​

Union: RelLogOp DependOnCols()() 0-4 RequiredCols(0, 1, 2, 3, 4)('Dates'[Year], 'Dates'[Month Num], ''[IsDM1Total], ''[SumxBug], ''[])
├── GroupSemiJoin: RelLogOp DependOnCols()() 0-3 RequiredCols(0, 1, 2, 3)('Dates'[Year], 'Dates'[Month Num], ''[IsDM1Total], ''[SumxBug])
│   ├── TreatAs: RelLogOp DependOnCols()() 0-2 RequiredCols(0, 1)('Dates'[Year], 'Dates'[Month Num])
│   │   └── TableCtor: RelLogOp DependOnCols()() 0-2 RequiredCols(0, 1, 2)(''[Value1], ''[Value2], ''[])
│   ├── Constant: ScaLogOp DependOnCols()() Boolean DominantValue=false
│   └── SumX: ScaLogOp MeasureRef=[SumxBug] DependOnCols(0, 1)('Dates'[Year], 'Dates'[Month Num]) Integer DominantValue=BLANK
│       ├── Scan_Vertipaq: RelLogOp DependOnCols(0, 1)('Dates'[Year], 'Dates'[Month Num]) 3-3 RequiredCols(0, 1, 3)('Dates'[Year], 'Dates'[Month Num], 'Dates'[Year])
│       └── Sum_Vertipaq: ScaLogOp DependOnCols(1, 3)('Dates'[Month Num], 'Dates'[Year]) Integer DominantValue=BLANK
│           ├── Scan_Vertipaq: RelLogOp DependOnCols(1, 3)('Dates'[Month Num], 'Dates'[Year]) 4-12 RequiredCols(1, 3, 6)('Dates'[Month Num], 'Dates'[Year], 'DFact'[Amount])
│           └── 'DFact'[Amount]: ScaLogOp DependOnCols(6)('DFact'[Amount]) Integer DominantValue=NONE
└── GroupSemiJoin: RelLogOp DependOnCols()() 0-3 RequiredCols(0, 1, 2, 3)('Dates'[Year], 'Dates'[Month Num], ''[IsDM1Total], ''[SumxBug])
    ├── TreatAs: RelLogOp DependOnCols()() 0-2 RequiredCols(0, 1)('Dates'[Year], 'Dates'[Month Num])
    │   └── TableCtor: RelLogOp DependOnCols()() 0-2 RequiredCols(0, 1, 2)(''[Value1], ''[Value2], ''[])
    ├── Constant: ScaLogOp DependOnCols()() Boolean DominantValue=true
    └── SumX: ScaLogOp MeasureRef=[SumxBug] DependOnCols(0)('Dates'[Year]) Integer DominantValue=BLANK
        ├── Scan_Vertipaq: RelLogOp DependOnCols(0)('Dates'[Year]) 3-3 RequiredCols(0, 3)('Dates'[Year], 'Dates'[Year])
        └── Sum_Vertipaq: ScaLogOp DependOnCols(0, 3)('Dates'[Year], 'Dates'[Year]) Integer DominantValue=BLANK
            ├── Scan_Vertipaq: RelLogOp DependOnCols(0, 3)('Dates'[Year], 'Dates'[Year]) 4-12 RequiredCols(0, 3, 6)('Dates'[Year], 'Dates'[Year], 'DFact'[Amount])
            └── 'DFact'[Amount]: ScaLogOp DependOnCols(6)('DFact'[Amount]) Integer DominantValue=NONE

逻辑结构图:

请添加图片描述

从逻辑查询计划来看,DAX 底层认为该计算可以由两部分通过 Union 合并而成:

  • Union 左边分支,从 Line 7 的代码可以看出,这部分计算 Date[Year]、Date[Month Num] 分组下的 SUM(DFact[Amount])​,这正是各个非总计行
  • Union 右边分支,从 Line 16 的代码可以看出,这部分计算 Date[Year] 分组下的 SUM(DFact[Amount])​,这正是两个总计行

物理查询计划

​image​

Union: IterPhyOp LogOp=Union IterCols(0, 1, 2, 3, 4)('Dates'[Year], 'Dates'[Month Num], ''[IsDM1Total], ''[SumxBug], ''[])
├── GroupSemijoin: IterPhyOp LogOp=GroupSemiJoin IterCols(0, 1, 2, 3)('Dates'[Year], 'Dates'[Month Num], ''[IsDM1Total], ''[SumxBug])
│   └── CrossApply: IterPhyOp LogOp=SumX IterCols(0, 1)('Dates'[Year], 'Dates'[Month Num])
│       ├── Spool_UniqueHashLookup: IterPhyOp LogOp=TreatAs LookupCols(0, 1)('Dates'[Year], 'Dates'[Month Num]) #Records=4 #KeyCols=2 #ValueCols=0
│       │   └── AggregationSpool<GroupBy>: SpoolPhyOp #Records=4
│       │       └── TreatAs: IterPhyOp LogOp=TreatAs IterCols(0, 1)('Dates'[Year], 'Dates'[Month Num])
│       │           └── TableCtor: IterPhyOp LogOp=TableCtor IterCols(0, 1, 2)(''[Value1], ''[Value2], ''[])
│       └── Spool_Iterator<SpoolIterator>: IterPhyOp LogOp=SumX IterCols(0, 1)('Dates'[Year], 'Dates'[Month Num]) #Records=4 #KeyCols=2 #ValueCols=1
│           └── AggregationSpool<Sum>: SpoolPhyOp #Records=4
│               └── CrossApply: IterPhyOp LogOp=Sum_Vertipaq IterCols(1, 3)('Dates'[Month Num], 'Dates'[Year])
│                   ├── Spool_MultiValuedHashLookup: IterPhyOp LogOp=Scan_Vertipaq LookupCols(1, 3)('Dates'[Month Num], 'Dates'[Year]) IterCols(0)('Dates'[Year]) #Records=4 #KeyCols=10 #ValueCols=0
│                   │   └── ProjectionSpool<ProjectFusion<>>: SpoolPhyOp #Records=4
│                   │       └── Cache: IterPhyOp #FieldCols=2 #ValueCols=0
│                   │           └── Spool_Iterator<SpoolIterator>: IterPhyOp LogOp=TreatAs IterCols(0, 1)('Dates'[Year], 'Dates'[Month Num]) #Records=4 #KeyCols=2 #ValueCols=0
│                   │               └── AggregationSpool<GroupBy>: SpoolPhyOp #Records=4
│                   │                   └── TreatAs: IterPhyOp LogOp=TreatAs IterCols(0, 1)('Dates'[Year], 'Dates'[Month Num])
│                   │                       └── TableCtor: IterPhyOp LogOp=TableCtor IterCols(0, 1, 2)(''[Value1], ''[Value2], ''[])
│                   └── Spool_Iterator<SpoolIterator>: IterPhyOp LogOp=Sum_Vertipaq IterCols(1, 3)('Dates'[Month Num], 'Dates'[Year]) #Records=4 #KeyCols=10 #ValueCols=1
│                       └── ProjectionSpool<ProjectFusion<Copy>>: SpoolPhyOp #Records=4
│                           └── Cache: IterPhyOp #FieldCols=2 #ValueCols=1
│                               └── Spool_Iterator<SpoolIterator>: IterPhyOp LogOp=TreatAs IterCols(0, 1)('Dates'[Year], 'Dates'[Month Num]) #Records=4 #KeyCols=2 #ValueCols=0
│                                   └── AggregationSpool<GroupBy>: SpoolPhyOp #Records=4
│                                       └── TreatAs: IterPhyOp LogOp=TreatAs IterCols(0, 1)('Dates'[Year], 'Dates'[Month Num])
│                                           └── TableCtor: IterPhyOp LogOp=TableCtor IterCols(0, 1, 2)(''[Value1], ''[Value2], ''[])
└── GroupSemijoin: IterPhyOp LogOp=GroupSemiJoin IterCols(0, 1, 2, 3)('Dates'[Year], 'Dates'[Month Num], ''[IsDM1Total], ''[SumxBug])
    └── Spool_Iterator<SpoolIterator>: IterPhyOp LogOp=SumX IterCols(0)('Dates'[Year]) #Records=2 #KeyCols=1 #ValueCols=1
        └── AggregationSpool<Sum>: SpoolPhyOp #Records=2
            └── Spool_Iterator<SpoolIterator>: IterPhyOp LogOp=Sum_Vertipaq IterCols(0, 3)('Dates'[Year], 'Dates'[Year]) #Records=4 #KeyCols=2 #ValueCols=1
                └── AggregationSpool<AggFusion<Sum>>: SpoolPhyOp #Records=4
                    └── CrossApply: IterPhyOp LogOp=Sum_Vertipaq IterCols(0, 3)('Dates'[Year], 'Dates'[Year])
                        ├── Spool_MultiValuedHashLookup: IterPhyOp LogOp=TreatAs LookupCols(1)('Dates'[Month Num]) IterCols(0)('Dates'[Year]) #Records=4 #KeyCols=2 #ValueCols=0
                        │   └── AggregationSpool<GroupBy>: SpoolPhyOp #Records=4
                        │       └── TreatAs: IterPhyOp LogOp=TreatAs IterCols(0, 1)('Dates'[Year], 'Dates'[Month Num])
                        │           └── TableCtor: IterPhyOp LogOp=TableCtor IterCols(0, 1, 2)(''[Value1], ''[Value2], ''[])
                        └── Cache: IterPhyOp #FieldCols=2 #ValueCols=1
                            ├── Spool_Iterator<SpoolIterator>: IterPhyOp LogOp=TreatAs IterCols(0, 1)('Dates'[Year], 'Dates'[Month Num]) #Records=4 #KeyCols=2 #ValueCols=0
                            │   └── AggregationSpool<GroupBy>: SpoolPhyOp #Records=4
                            │       └── TreatAs: IterPhyOp LogOp=TreatAs IterCols(0, 1)('Dates'[Year], 'Dates'[Month Num])
                            │           └── TableCtor: IterPhyOp LogOp=TableCtor IterCols(0, 1, 2)(''[Value1], ''[Value2], ''[])
                            └── Spool_Iterator<SpoolIterator>: IterPhyOp LogOp=Scan_Vertipaq IterCols(0, 3)('Dates'[Year], 'Dates'[Year]) #Records=2 #KeyCols=10 #ValueCols=0
                                └── ProjectionSpool<ProjectFusion<>>: SpoolPhyOp #Records=2
                                    └── Cache: IterPhyOp #FieldCols=1 #ValueCols=0
                                        └── Spool_Iterator<SpoolIterator>: IterPhyOp LogOp=TreatAs IterCols(0, 1)('Dates'[Year], 'Dates'[Month Num]) #Records=4 #KeyCols=2 #ValueCols=0
                                            └── AggregationSpool<GroupBy>: SpoolPhyOp #Records=4
                                                └── TreatAs: IterPhyOp LogOp=TreatAs IterCols(0, 1)('Dates'[Year], 'Dates'[Month Num])
                                                    └── TableCtor: IterPhyOp LogOp=TableCtor IterCols(0, 1, 2)(''[Value1], ''[Value2], ''[])

完整的流程结构图如下:

在这里插入图片描述

这个案例的物理查询计划同逻辑查询计划的流程结构相似,也是将整个计算区分成总计行和非总计行的计算最后再合并起来,简化表达为如下流程:

在这里插入图片描述

实际计算过程

仔细阅读物理查询计划后,对计算过程有了一定的了解,我把整体流程数据流大致演示一下(省略了几个分组的操作,对理解本案例并没有影响):

​底层计算过程模拟截图​

(在 DAX 底层计算过程中,经常能看到一些步骤通过合并查询,切换来自不同源的同一列,这些不同来源的列通过列后面的数字来标识,比如 Year(0),可能来自 TreatAS,而 Year(3) 则来自 VQ4,相同来源的列可以通过 Lookup 操作符进行匹配,不同来源的列则要通过 HashLookup 来匹配。 )

30 和 70 这两个计算结果由右侧【计算总计行】分支产生,需要重点理解下该部分的计算过程。

1、该分支从 VQ4 查询开始,前面讲过了,该数据缓存中包含有切片器未选择的 2019年11、12月 和 2020年1、2月相关数据。

2、中间的步骤是在切换 Year(3) 到 Year(0) ,Year(3) 来自 VQ4,Year(0)来自 TreatAs,具体的做法是将 VQ4 与 TreatAs 表构造器{ ( 2019, 1 ), ( 2019, 2 ), ( 2020, 11 ), ( 2020, 12 ) } ​通过 [Month Num] 列进行匹配,比如 VQ4 中的 2020年1月 ,通过 [Month Num] = 1,从 TreatAs 中匹配到 Year(0)=2019,于是出现了红框这行数据

​image​

3、按 Year(0) 进行分组汇总,于是在 Year(0) = 2019 组内,实际包含的是 2019年1、2月 和 2020年1、2月的数据,最后的计算结果是 1+2+13+14 = 30

​image​

‍

问题分析

通过上述分析,可以了解到如下情况:

  1. SUMMARIZECOLUMNS 分别计算总计行和非总计行,最后合并起来得到最终结果
  2. VQ4 中的 WHERE 子句使用的 Dates[Year] And Dates[Month Num] ,破坏了切片器构成的固化筛选器,导致查询结果中不仅有 2019年1、2月,2022年11、12月,还包含了 2019年11、12月、2020年1月、2月
  3. 底层计算时按照固化筛选器中的 [Month Num] 去匹配 [Year] ,导致最后分组计算时,在2019年分组下包含有 2020年的数据。

由此可知,VQ4 WHERE 子句Dates[Year] IN ( 2019, 2020 ) VAND Dates[Month Num] IN ( 12, 1, 2, 11 ) ​ 破坏了 TREATAS ({ ( 2019, 1 ), ( 2019, 2 ), ( 2020, 11 ), ( 2020, 12 ) },'Dates'[Year], 'Dates'[Month Num]))​ 构造的固化筛选器,是导致总计行计算错误的关键原因。

DAX 底层并不会像 DAX 理论那样逐步去分析计算各个筛选上下文之间的关系,而是直接根据代码得出它需要使用的 xmSQL 数据再进行后续处理。DAX 理论是用来指导用户让用户可以预测出于代码的预测结果,应当与 DAX 底层计算结果保持一致。

显然在本案例中,DAX 理论与实际计算结果无法保持一致且无法调和,DAX 理论无法解释 DAX 底层为什么会使用 VQ4 这样的数据去计算本案例中的 DAX 查询代码。

为了定位问题发生的根源,做一些猜测,然后设计实验排查,希望运气够好能够早点定位到关键因素:

  1. SUMMARIZECOLUMNS 与 迭代器 的配合,本案例中,尤其是在计算总计行时
  2. SUMMARIZECOLUMNS 中 参数作用于参数表的方式
  3. …待补充

‍

实验设计

猜想1好验证,从报表中把 [Month Num] 去掉,直接在 [Year] 这个维度上进行计算,看看没有了总计行那部分的计算,结果会不会有所不同。

猜想2不好验证,需要观察更多的数据计算表现,搜集更多信息

那就在下一篇中来验证猜想1吧。

PowerBI之DAX实战:从聚合、统计到表操作与关系函数的场景化应用 本文深入探讨了PowerBI中DAX函数的实战应用,从基础的聚合与统计函数(如SUMX、RANKX)到高级的表操作函数(如SUMMARIZECOLUMNS、ADDCOLUMNS)与关系函数(如RELATED、TREATAS),通过电商数据分析场景,系统讲解了如何构建动态计算指标与交互式仪表盘,是掌握PowerBI核心分析能力的关键指南。 阅读详情

相关推荐

2.23 PowerBI数据建模-动态累计求和的实战应用

本文深入探讨了PowerBI数据建模中动态累计求和的实战应用,通过具体案例和DAX代码示例,展示了如何实现单维度和多维度的动态累计计算。文章详细解析了动态累计求和在帕累托分析、进度监控等商业场景中的核心价值,并提供了性能优化技巧和典型业务场景的应用案例,帮助用户提升数据分析效率。

weixin_28731223的博客 372

power bi求和错误

https://www.jianshu.com/p/2eeb3092ab18

weixin_42578783的博客 1296

Power BI中SUMMARIZE函数核心原理与企业级实战指南

SUMMARIZE是DAX中关键的表构造函数,用于在内存中动态生成分组汇总表,其本质并非聚合而是可控的虚拟物化——先按指定列分组,再通过ADDCOLUMNS等函数注入计算逻辑。它天然支持行上下文与筛选上下文协同,在RFM客户分层、销售漏斗分析、预算偏差对比等多维建模场景中不可替代。相比SUMMARIZECOLUMNS,它具备更强的上下文稳定性与调试友好性;相比GROUPBY,它支持非聚合字段直接输出,灵活性更高。掌握分组列处理、CURRENTGROUP()上下文穿透及预筛选优化,是提升Power BI复杂度

weixin_29040367的博客 256

SUMMARIZE函数解决之前的总计错误

小伙伴们,还记得之前的总计栏显示错误问题么? 本期呢,白茶决定来研究解决这个问题,先来看看之前的样例。 放上之前的每笔成交代码: 每笔成交花费 = VAR CQ = [每一笔消费达成日期] VAR DQ = IF ( SUM ( Sheet1[销售额] ) > 0, CALCULATE ( [每一笔消费达成日期], FILTER ( ALL ( Sheet1[日期] ), .

Fabric丨白茶 2016

别再死记硬背DAX函数了!用这3个真实业务场景(销售分析/客户分层/动态排名)彻底搞懂PowerBI表操作

本文通过销售分析、客户分层和动态排名三个真实业务场景,深入解析PowerBI中DAX表操作函数的实战应用。重点介绍SUMMARIZECOLUMNS、VALUES和RANKX等核心函数的高效使用技巧,帮助数据分析师摆脱死记硬背,掌握灵活解决业务问题的能力,提升报表自动化水平。

weixin_42531710的博客 365

SUMMARIZECOLUMNS 的疑似 bug(1)引言

与 Excel 通过 MDX 创建报表的方式不同,PowerBI 在代码层面主要是通过 SUMMARIZECOLUMNS​ 函数计算报表中各个视觉对象,它实现了 MDX 中的 auto-exist 功能并具有诸多特性,能够在许多场景中代替ADDCOLUMNS​+ SUMMARIZE​的应用。在特定情况下,SUMMARIZECOLUMNS ​的计算结果似乎并不符合 DAX 理论,本篇介绍这些疑似存在 BUG 的现象。

一棵松的博客 1382

Power BI中summarizecolumns函数、sum函数实现SQL Server中的group by分组汇总

Power BI是微软开发的一款功能非常强大的的BI工具,可以制作非常美观的报表,但这个工具的核心是DAX,翻译为中文就是 数据分析表达式,有点类似于excel函数,但又很不一样。 DAX中的很多功能可以与SQL对应,但差异也很大。   下载Power BI 以及 输入实验数据,请参考前一篇文章: Power BI中selectcolumns函数+related函数实现SQL Server中...

SQL Server探索 1万+

DAX 底层计算过程演示——ADDCOLUMNS + 复杂上下文环境

关于 DAX 理论的资料很多,DAX 理论帮助我们理解和预测 DAX 的计算结果,但 DAX 在底层实际是怎么计算的却少有人谈及。本篇以一段在复杂上下文环境中通过 ADDCOLUMNS 进行计算的 DAX 查询代码为观察对象,使用 DAX Stuido 查看查询计划,展示其在存储引擎中执行了哪些数据查询,揭示公式引擎如何组装这些数据最终得出计算结果。

一棵松的博客 2071

Power BI基础操作-SUMMARIZECOLUMNS()函数

软件打开及数据导入 打开软件之后要求登录账号或者免费试用,这时直接点击右上角叉号即可。 点击“获取数据”,选择相应的数据类型。点击“加载”。 创建新数据集 点击“输入数据”。 添加完成后,点击“加载”即可。 SUMMARIZECOLUMNS()函数 函数作用:分组聚合 语法:SUMMARIZECOLUMNS(第1参数,第2参数,第3参数,第4参数) 位置 参数 描述 第1参数 GroupBy_ColumnName 分组依据,可重复,可用于小计和总计函数 第2参数 Filt.

m0_46305747的博客 9911

OpencvSharp学习笔记(一):图片的打开,保存灰度化,保存

近来萌生了学习OpenCv的想法,经过度娘得知老夫会的C#不能直接用OpenCv,只能用他的儿子OpenCvSharp与EmguCV,奈何奈何,这两玩意的资料少的出奇,只能慢慢的摸索了,EmguCV先不说,老夫找到了牛批的资料,先摸索OpencvSharp吧 首先打开VS通过Nuget安装 选择版本后点击安装就OK了. 安装完成后,引用里面就有以下的玩意儿了… 废话不多说了,在写程序前先 using OpenCvSharp 图片打开,灰度化,保存代码如下: static void Main(strin

猥琐de专注 7188

WSL2 Ubuntu复现FoundationPose项目(docker)

复现一个基于深度学习的物体姿态估计框架FoundationPose项目,使用docker,WSL2

woaidawangwang的博客 2000

SUMMARIZECOLUMNS 的疑似 bug(4)验证触发条件

上一篇发现总计行并不是关键点,并根据观察到的现象猜测了3个关键点,本篇通过单变量控制实验逐一对其进行验证,判断哪些条件会触发计算结果与 DAX 理论不符的情况,并最终确认了这些条件。

一棵松的博客 799

英飞凌功率MOSFET SPICE 瞬态仿真不收敛问题解决(基于TINA)

英飞凌功率MOSFET SPICE仿真容易出现不收敛问题,这个对于IGBT和SIC的管子应该是一样的,在瞬态仿真分析中,出现如下图所示的报错,Convergence problem。spice是为线性电路设计的,例如运算放大器、线性电源等,不是专门仿真开关电路的。在瞬态仿真时,仿真器是要不断迭代求解的,开关快速的跳变,容易在迭代式出现不收敛的问题。,由于时间步长减少,会消耗更多的计算机内存,如果运行多次内存消耗过大,会报“Out of memory”.解决方法是:报错工程,重启软件,内存重新计算。

miaoxiaokeji的博客 2298

SUMMARIZECOLUMNS 的疑似 bug(3)总计行是否关键点

上一篇介绍了在总计行中出现与理论预期不符的结果,通过物理查询计划了解其底层计算过程,猜想是否 `SUMMARIZECOLUMNS`​函数对总计行的计算存在什么特殊算法,本篇验证在非总计行中进行计算的情况,以帮助判断总计行是否是关键点。

一棵松的博客 1087

嘉立创EDA vs Altium Designer:新手如何选择?从界面到实战全对比

本文全面对比了嘉立创EDA与Altium Designer(AD)两大PCB设计工具,从设计哲学、界面交互、封装库管理、设计规则引擎、协作功能到成本生态六大维度进行深入分析。嘉立创EDA以极简设计和云端协作为特色,适合学生和创客快速上手;而AD则凭借专业级精准控制,成为高端电子设计的行业标准。通过实战案例和详细对比表格,帮助新手根据项目需求选择合适的EDA工具。

weixin_30296405的博客 721

思科9117AP从零配置EWC模式实战:Wi-Fi6网络搭建避坑指南

本文详细介绍了思科9117AP在Wi-Fi6网络环境下配置EWC模式的实战指南,涵盖镜像准备、网络环境配置、模式转换步骤及高级运维技巧。通过EWC模式,企业可实现控制器与AP的一体化部署,显著降低成本和简化运维,特别适合中小企业Wi-Fi6网络搭建。

weixin_28318011的博客 333

SUMMARIZECOLUMNS 的疑似 bug(5)最终结论

上一篇找到了触发 `SUMMARIZECOLUMNS`​ 计算的结果不符合 DAX 理论的充分条件,这一篇尝试探讨修正理论对其进行解释,在这一篇中,我以为找到了一个合理的理论假设,但随后一个新的发现给了我当头一棒,这一篇应该是本系列的最后一篇,我必须直面现实了。

一棵松的博客 1560

多思计算机组成原理实验:模型机课程设计

计算机组成原理实验教程 基于多思网络虚拟实验系统 张雯雰

Nick的博客 2万+

DAX:翻译《介绍SUMMARIZECOLUMNS》

原文:Introducing SUMMARIZECOLUMNS 建议用SUMMARIZECOLUMNS来代替SUMMARIZE函数,和ADDCOLUMNS/SUMMARIZE的组合。下面两个DAX的结果是一样的: Sales by Year and Color new style = SUMMARIZECOLUMNS ( 'Date'[Calendar Year], 'Prod...

悦光阴的博客 619

标准高斯过程回归(Gaussian Processes Regression, GPR)从零开始,公式推导

标准高斯过程回归从零开始公式推导

qq_43587949的博客 1万+

【MATLAB】嵌入式PID控制参数整定与优化

本文提出了一种基于MATLAB仿真的嵌入式PID参数优化方法,解决了传统人工试凑法效率低、适应性差的问题。通过建立一阶滞后被控对象模型,对比分析了不同PID参数组合的性能表现,筛选出最优参数。仿真结果表明,优化后的PID参数能有效降低超调量(从传统方法的显著超调降至接近0%),缩短调节时间,提高稳态精度。最终将优化算法部署到STM32平台,实现了"仿真整定-参数优化-嵌入式落地"的完整开发流程。该方法显著提升了嵌入式系统的响应速度和控制精度,为工业控制应用提供了标准化解决方案。

unber的博客 46

6.13 PowerBI系列之DAX函数专题-summarize,rollup和summarizecolumns以及groupby

summarizecolumns(一个query)>summarize>(两个query语句)>groupby(复杂一些),powerbi视觉对象后台生成的DAX表达式也是默认使用summarizecolumns。filter(‘sales’,‘sales’[产品类别]=“配件”),5.rollup做小计在summarize中使用。4.分组函数中的列可以来自模型中的不同表;sum(‘sales’[订单金额])) //只取配件的汇总 (图4)‘sales’[产品子类别],‘sales’[产品类别],

qq_33842426的博客 2020

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

PowerBI之DAX 2:聚合、统计、关系、表操作函数

SUM是DAX中最常用的聚合函数,它只有一个参数:<column>销售总额 = SUM( '订单表'[销售额] )<table>:将要进行计算的表,可以是FILTER表表达式计算得到的筛选表:对表中每一行进行计算的表达式所以SUMX返回的就是:对表的每一行按表达式进行计算,再进行求和。销售总额 =SUMX( '订单表','订单表'[销售额] )由于SUM函数只有一个参数,决定了它只能处理一个表的一列的求和,而涉及到多列/多表的计算,或者对特定表达式的求和,它就不适用了。

qq_56591814的博客 4338

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

2.26 PowerBI数据建模-排名前三的人名及销量(SUMMERIZECOLUMNS+CONCATENATEX)

给上下文中的人员配上一列排名形成一个VAR过程表,取这个表中排名小于等于3的人名列,每一行的值用CONCATENATEX合并到一起,用逗号隔开,按销量降序,遇到销量相同,用人员升序。像上一个度量值做出VAR过程表后,筛选排名小于等3的行,对销量列求和(此处VAR表中没有销量列,筛选上下文传递到了销量表)。有如下一张销售表,写一个度量值,提取销售前三名人员的名字,用逗号隔开,按照销量降序排列,遇到并列,用人名升序排列。人员按销量排名,此处为随上下文变化的动态排名,用的ALLSELECTED。

PowerBI自己学 618

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Power BI DAX性能优化:5个导致报表卡顿的致命写法

DAX是Power BI的核心计算语言,其执行效率直接受VertiPaq列式引擎特性影响。理解布尔筛选、临时表物化、迭代器开销等底层原理,是实现高性能报表的关键技术基础。当DAX公式触发FILTER隐式建表、SUMX无节制迭代、RELATED长链跳转、ALL引发上下文爆炸或ISINSCOPE高频判断时,会严重破坏位图索引与向量化执行路径,导致加载延迟激增。这些模式在真实生产环境(如零售销售仪表板、电商GMV看板)中高频出现,常表现为10秒级以上响应延迟。本文聚焦可立即落地的工程化修复方案,覆盖CALCULA

duiker 485
上一篇: SUMMARIZECOLUMNS 的疑似 bug(1)引言
下一篇: SUMMARIZECOLUMNS 的疑似 bug(3)总计行是否关键点
apinerand
博客等级 码龄9年 201粉丝 11原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值