nude SUM
和sum wrap in有CALCULATE
什么区别?
Measure1 = SUM( tab[col1]) )
Measure2 = CALCULATE ( SUM( tab[col1]) ) )
Run Code Online (Sandbox Code Playgroud)
更新。
我得到了其他SO问题的答案,该问题使用包装的计算。问题的作者对此做了解释,但我仍然不明白。这是作者建议的措施:
Expected Result =
SUMX (
VALUES ( Unique_Manager[Manager] ),
VAR SumBrand = CALCULATE ( SUM ( Budget_Brand[BudgetBrand] ) )
VAR SumProduct = CALCULATE ( SUM ( Budget_Product[BudgetProduct] ) )
RETURN
IF ( ISBLANK ( SumProduct ), SumBrand, SumProduct )
)
Run Code Online (Sandbox Code Playgroud)
并说明:
(...)请注意,我将总和打包在CALCULATE中。这样做是为了执行从SUMX内部的行上下文(特定的Manager)到将该Manager用作BudgetBrand和BudgetProduct上的筛选器上下文的上下文转换。将这些和存储为变量会使IF行更易读,并且仅要求SumProduct一次计算而不是两次。
我知道什么是过滤器上下文。但是我不明白什么是上下文转换。还有其他过渡吗?
这个答案解决了一般情况下的使用CALCULATE
,涵盖了过滤器上下文、行上下文和上下文转换的主题。
正如原始问题中所定义的,根据下面的原始响应,[Measure1] 和 [Measure2] 的行为相同。请参阅对此答案的编辑,以更全面地处理CALCULATE
.
一般来说,如果您正在查看行上下文中的表达式,您将使用CALCULATE
单个参数来引发上下文转换(行上下文 -> 筛选器上下文)。
我发现的一个常见的初学者错误是CALCULATE
表达式中多余/不必要的 s。CALCULATE
仅当您想要影响第一个参数的过滤器上下文时才应使用。这有两种一般形式:
两者可能会走到一起。
上述推论是,CALCULATE
除非调用站点位于行上下文中,否则您永远不应该使用一个参数。
编辑:根据评论和更新的问题
看来这个问题有些混乱。因此,在进行上下文转换之前,我将首先澄清这一点。
注意:无论我在CALCULATE
下面提到什么,您都可以阅读CALCULATETABLE
,其行为几乎相同。第一个用于标量表达式,第二个用于表表达式。
度量不仅仅是一个命名的 DAX 表达式。度量是一个带有隐式CALCULATE
包装的命名 DAX 表达式。因此,如果您想用度量的表达式替换对度量的引用,您不只是进行简单的文本替换,您可以编写CALCULATE ( <measure body> )
.
如果问题的提问形式是自洽的,我会尽量不去猜测问题的不同含义。我相信你想问的是:
以下 DAX 表达式有什么区别:
SUM ( 'tab'[col1] )
和
CALCULATE ( SUM ( 'tab'[col1] ) )
这与您提出的问题有本质上的不同,因为您询问的是两个完全定义的度量,而不是 DAX 的两个片段。这些度量的行为相同,因为它们的扩展在逻辑上是等效的:
//Measure 1 definition:
Measure1 = SUM ( 'tab'[col1] )
// Measure 1 expands to the following, and you would use this if you were
// replacing a reference with code:
//Expansion1:
CALCULATE ( SUM ( 'tab'[col1] ) )
Run Code Online (Sandbox Code Playgroud)
//Measure2 definition and expansion:
Measure2 = CALCULATE ( SUM ( 'tab'[col1] ) )
//Expansion2:
CALCULATE ( CALCULATE ( SUM ( 'tab'[col1] ) ) )
Run Code Online (Sandbox Code Playgroud)
因此,您的测量在语义上(尽管不是文本上)是相同的。两者都表现为SUM
包裹在CALCULATE
. [Measure2]恰好CALCULATE
在扩展时多了一个。
那么它有什么CALCULATE
作用呢?很多。作为参考,当我进行 DAX 培训时,CALCULATE
筛选器和行上下文是一个数小时的部分。
CALCULATE
执行以下操作。
执行上下文转换。它创建一个新的过滤器上下文,在其中计算其第一个参数表达式。这个新的过滤器上下文包含以下内容(合并到单个过滤器上下文中):
A。无论调用站点存在什么外部过滤器上下文CALCULATE
b. 无论调用点存在什么行上下文CALCULATE
评估 args 2-N (称为 setfilters)以修改(添加、删除或修改现有)步骤 (1) 中的过滤器上下文,最后
在由步骤 (1) 和 (2) 确定的新过滤器上下文中计算 arg1 中的表达式。
因此,这引出了几个问题,即:
因此,首先,过滤上下文。筛选器上下文来自多个 DAX 函数,包括CALCULATE
、CALCULATETABLE
、SUMMARIZE
、SUMMARIZECOLUMNS
和GROUPBY
。此列表并非详尽无遗,但涵盖了一些非常常见的功能。
每当您与报告工具(例如 Excel 数据透视表或 Power BI 报告)中的表格模型交互时,您在 GUI 中的操作都会生成用于填充任何视觉对象的查询。从这些(和其他)报告工具的角度来看,过滤器上下文来自:
您可以将过滤器上下文视为一组“表”[列]->值映射。无论选择什么文字值,或满足选择标准,都将成为过滤器上下文。
例如,让我们考虑一个矩阵视觉效果,其中行为“日历”[年份],列为“日历”[月份名称],切片器为“产品”[类别]=“服装”,页面级筛选器为“日历” [年份]>2015年。我们将查看度量 [M] 的筛选器上下文,该度量在第三行第四列的矩阵中进行评估(2018 年 4 月)
Filter Context:
'Calendar'[Year]=2018
'Calendar'[Year]>2015
=> 'Calendar'[Year] IN {2016, 2017, 2018, ..., N} // for whatever years exist in the calendar
'Calendar'[Month]="April"
'Product'[Category]="Clothing"
Run Code Online (Sandbox Code Playgroud)
矩阵的每个单元格都会有自己的基于年和月交集的过滤器上下文,但其余部分将保持不变。对于底部的总计行,过滤器上下文将没有来自矩阵的特定年份,但仍会受到页面级过滤器的影响。对于右侧的总计列,不会有月份上下文,但会有特定年份的上下文。对于矩阵右下角的拨款总额单元格,唯一的过滤器是:
'Product'[Category]="Clothing"
'Calendar'[Year]>2015 //from the page-level
Run Code Online (Sandbox Code Playgroud)
总之,过滤器上下文与您可能理解的内容非常一致。我发现对于大多数人来说,过滤上下文本身是有意义的。
现在介绍行上下文。每当我们迭代表时,行上下文就存在。您将在两个地方找到行上下文:
SUMX
、AVERAGEX
等...)FILTER
ADDCOLUMNS
每当我们谈论行上下文时,我们都在谈论迭代。您可以将 for 循环想象为:
//pseudocode
for row in table:
<expression>
Run Code Online (Sandbox Code Playgroud)
您还可以将行上下文视为类似于 SQL 游标,迭代表的行。它在很大程度上相当于快进、只读游标。
我们一次考虑一行。行上下文由正在迭代的表的列中的一组文字值组成。
因此,给定一个包含列(Id、金额、日期)的表“T”,行上下文由SUMX ( 'T', <expression )
“T”[Id]、“T”[金额] 和“T”[日期] 的特定值组成。您可以通过 中的列引用来引用这些值中的任何一个<expression>
。您还可以使用表值函数作为迭代器的第一个参数,例如SUMX ( VALUES ( 'T'[Date] ), <expression> )
。在本例中,我们迭代的表是 的返回值VALUES ( 'T'[Date] )
,它是 'T'[Date] 列中唯一值的集合。在这种情况下,行上下文仅包含 'T'[Date] 中的值 - 'T' 的其余部分不在行上下文中。
注意:当我们处于行上下文中时,我们可以通过名称引用列而不聚合它 - 这在 DAX 中的任何地方都无效,除了在行上下文中。
注2:基本聚合函数如SUM
或COUNTROWS
与行上下文没有交互。因此,对于下面的表格和表达式,我们将看到可能没有意义的结果:
//Table, 'T' with schema as above
{
(1, 10, 2019-02-01),
(2, 20, 2019-02-01),
(3, 30, 2019-03-01),
(4, 40, 2019-03-02)
}
//Add calculated column to 'T'
C = SUM ( 'T'[Amount] )
// Result would be 100 on every row - the total of 'T'[Amount]
//Measure on a card visual with no other filters:
M = SUMX ( 'T', SUM ( 'T'[Amount] ) )
// Result would be 400, which is the sum of 'T'[Amount] calculated once per row
// and summed together
//M2 on card with no other filters
M2 = SUMX ( VALUES ( 'T'[Date] ), SUM ( 'T'[Amount] ) )
// Result is 300, which is the sum of 'T'[Amount] calculated once per unique date
// and summed together
Run Code Online (Sandbox Code Playgroud)
当我们处于行上下文中并且希望该行上的值有助于过滤器上下文时,我们可以将聚合包装在 a 中,CALCULATE
以将行上下文转换为过滤器上下文。这称为上下文转换。
// Same table as above:
M3 = SUMX ( VALUES ( 'T'[Date] ), CALCULATE ( SUM ( 'T'[Amount] ) ) )
// result on card would be 100, the actual total
Run Code Online (Sandbox Code Playgroud)
我们可以将计算分解为以下迭代:
// Input table would be {2019-03-02, 2019-02-01, 2019-03-01}
//Iteration1:
1. Row context: 'T'[Date]=2019-03-02
2. CALCULATE transitions 'T'[Date] value to Filter context: 'T'[Date]=2019-03-02
3. SUM is evaluated in filter context from step (2)
4. Result of iteration1 = 40
//Iteration2:
1. Row context: 'T'[Date]=2019-02-01
2. CALCULATE transitions 'T'[Date] value to Filter context: 'T'[Date]=2019-02-01
3. SUM is evaluated in filter context from step (2)
4. Result of iteration1 = 30 //note both [Amount]s for 2019-02-01 contribute to this
//Iteration3:
1. Row context: 'T'[Date]=2019-03-01
2. CALCULATE transitions 'T'[Date] value to Filter context: 'T'[Date]=2019-03-01
3. SUM is evaluated in filter context from step (2)
4. Result of iteration1 = 30
// Final result - combine iteration results with sum:
40 + 30 + 30 = 100
Run Code Online (Sandbox Code Playgroud)
请注意,过滤器上下文会自动导航模型中的关系。行上下文仅包含正在迭代的表中的值。如果需要在行上下文中导航关系,可以使用RELATED
或,或者可以使用或RELATEDTABLE
将行上下文转换为筛选上下文。CALCULATE
CALCULATETABLE
因此,在您链接的示例中:
Expected Result =
SUMX (
VALUES ( Unique_Manager[Manager] ),
VAR SumBrand = CALCULATE ( SUM ( Budget_Brand[BudgetBrand] ) )
VAR SumProduct = CALCULATE ( SUM ( Budget_Product[BudgetProduct] ) )
RETURN
IF ( ISBLANK ( SumProduct ), SumBrand, SumProduct )
)
Run Code Online (Sandbox Code Playgroud)
SumBrand
是当前行上下文中“Unique_Manager”[Manager] 的“Budget_Brand”[BudgetBrand] 之和,即迭代中当前行值的管理器。同样,SumProduct
是行上下文中经理的“Budget_Product”[BudgetProduct] 的总和。
您可以轻松定义以下内容:
Brand Budget = SUM ( 'Budget_Brand'[BudgetBrand] )
Product Budget = SUM ( 'Budget_Product'[BudgetProduct] )
Expected Result =
SUMX (
VALUES ( 'Unique_Manager'[Manager] ),
VAR SumBrand = [Brand Budget]
VAR SumProduct = [Product Budget]
RETURN
IF ( ISBLANK ( SumProduct ), SumBrand, SumProduct )
)
Run Code Online (Sandbox Code Playgroud)
我可能会重构如下,以便您只在需要时计算品牌预算:
Expected Result =
SUMX (
VALUES ( 'Unique_Manager'[Manager] ),
VAR SumProduct = [Product Budget]
RETURN
IF ( ISBLANK ( SumProduct ), [Brand Budget], SumProduct )
)
Run Code Online (Sandbox Code Playgroud)
不过,无论有没有重构,上面引用测量的版本在语义上都与 inlines 的版本相同CALCULATE ( SUM ( ... ) )
。
这是因为,正如本编辑部分前面所述,以下两个是等效的:
Measure = SUM ( 'tab'[col1] )
Run Code Online (Sandbox Code Playgroud)
CALCULATE ( SUM ( 'tab'[col1] ) )
Run Code Online (Sandbox Code Playgroud)
我希望这有助于理解为什么我如此勇敢地回答你原来的问题。作为度量,您的两个表达式在语义上是等效的。作为孤立的表达,它们并非如此。
归档时间: |
|
查看次数: |
171 次 |
最近记录: |