加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

筛选CALCULATE函数中的参数

(2023-07-06 17:54:41)
标签:

powerbi

可视化

数据分析

bi

分类: 数据分析

本文翻译自Marco Russo的文章—《Filter Arguments in CALCULATE》来源:SQLBI 在CALCULATE函数中,筛选参数始终是一个迭代器。找到适当的粒度对其进行控制,对结果和性能非常重要。本文介绍在DAX中创建复杂筛选条件的可用选项。


CALCULATE函数的筛选基础知识

在编写CALCULATE语句时,所有的筛选参数都是表达式,如一个或多个列的值列表,或整个表格的值列表。例如,当您编写以下语句时:

CALCULATE (

,

table[column] =

)

实际上,您所编写的筛选表达式会被转换为:

CALCULATE (

,

FILTER (

ALL ( table[column] ),

table[column] =

)

)

实际上,对于CALCULATE和CALCULATETABLE的所有筛选参数,此行为是相同的。从此处开始,我们将描述这些函数中筛选参数的语法,通过以下一般语法标识:

CALCULATE (

,

,

,

...,

 

)

CALCULATETABLE (

 

,

,

,

...,

 

)

一个筛选函数可以是一个逻辑表达式或者一个表格表达式。

table[column] =

FILTER ( ... )

ALL ( ... )

这里的“...”可以是任何其他允许在筛选参数中的表格表达式。

复杂的筛选参数

由DAX自动生成的自动FILTER函数在代替逻辑表达式时,DAX语法要求在筛选表达式中只表达一个单列。因此,您可以编写:

[Sales Red or Blue] :=

CALCULATE (

[Sales Amount],

Product[Color] = "Red" || Product[Color] = "Blue"

)

上述语法在内部会被转换为以下语法,您也可以显式编写以获得与您的DAX度量值相同的行为。

[Sales Red or Blue] :=cv

CALCULATE (

[Sales Amount],

FILTER (

ALL ( Product[Color] ),

Product[Color] = "Red" || Product[Color] = "Blue"

)

)

然而,您不能编写一个单一的筛选参数引用两个不同的列。

[Sales Red or Contoso - invalid] :=

CALCULATE (

[Sales Amount],

'Product'[Color] = "Red" || 'Product'[Brand] = "Contoso"

)

在这种情况下,您需要显式编写一个表格表达式,而不是依靠CALCULATE和CALCULATETABLE自动将逻辑表达式转换为表格表达式的机制,当您引用一个单列时。您有几种选项可用,可以产生不同的结果,并且可能具有不同的性能。

表格筛选

您可以使用对包含两列的整个表格进行筛选,以在两个列上编写筛选条件。

[Sales Red or Contoso - table filter] :=

CALCULATE (

[Sales Amount],

FILTER (

'Product',

'Product'[Color] = "Red" || 'Product'[Brand] = "Contoso"

)

)

使用表格筛选,您会继承产品表中已存在的筛选参数,因此如果产品“Red”或“Contoso”品牌在已有的筛选中不存在,您将不会包括它们。更重要的是,您不会覆盖该列上的现有筛选条件。因此,如果您有一个切片器筛选品牌为“Proseware”,您将只看到属于“Proseware”品牌中产品为“Red”的销售额,忽略任何“Contoso”品牌的产品。

ALL列筛选

您可以通过创建一个只包含所需列的特殊表格来对两个列进行筛选。通过使用ALL函数,您可以获得一个表格,其中包含基础表格中引用列的所有唯一值组合。

[Sales Red or Contoso - ALL columns filter] :=

CALCULATE (

[Sales Amount],

FILTER (

ALL ( 'Product'[Color], 'Product'[Brand] ),

'Product'[Color] = "Red" || 'Product'[Brand] = "Contoso"

)

)

在这种情况下,筛选条件的基数可能会低于引用列中的值的笛卡尔积。为了获得这样的列表,引擎必须执行表格扫描。对于大型表格中的低基数列,这可能是昂贵的操作。

此筛选的结果将覆盖对指定列的任何现有筛选。例如,如果您有一个切片器筛选品牌为“Proseware”,您将看到产品“Red”的销售金额,而不管其品牌如何,将其与整个“Contoso”品牌的销售额相加,而不管颜色如何 - 但是红色和Contoso品牌的产品将仅计算一次,避免重复计算其值。

CROSSJOIN列筛选

一个替代前一节中描述的ALL筛选的方法是使用CROSSJOIN,对两列的所有值进行CROSSJOIN。使用CROSSJOIN,你可以获得你所引用的列中所有可能的数值组合,而不考虑这些组合是否存在于基础表中。

[Sales Red or Contoso - CROSSJOIN columns filter] :=

CALCULATE (

[Sales Amount],

FILTER (

CROSSJOIN (

ALL ( 'Product'[Color] ),

ALL ( 'Product'[Brand] )

),

'Product'[Color] = "Red" || 'Product'[Brand] = "Contoso"

)

)

在这种情况下,筛选条件的基数与引用列中的值的笛卡尔积相同。为了获得这样的列表,引擎不执行表格扫描,而只使用两列中可用的值列表。对于具有高基数且存在高相关性的列而言,这可能是昂贵的,因为表格中现有组合的数量远远低于所有可能的组合。

这种筛选的结果与ALL列筛选完全相同,只是两种方法可能会有不同的性能表现。最佳方法取决于表格和筛选列的基数。但是,您可以使用CROSSJOIN将不同表格的列进行组合,而使用ALL语法则无法实现。

SUMMARIZE列筛选

如果您不希望使用ALL和CROSSJOIN具有的筛选替换行为,而是希望保留使用表格筛选时的现有筛选条件,您可以使用KEEFPILTERS来包装ALL/CROSSJOIN筛选条件,或者您可以使用SUMMARIZE。以下是使用KEEFPILTERS的语法:

[Sales Red or Contoso - ALL KEEPFILTERS] :=

CALCULATE (

[Sales Amount],

KEEPFILTERS (

FILTER (

ALL ( 'Product'[Color], 'Product'[Brand] ),

'Product'[Color] = "Red" || 'Product'[Brand] = "Contoso"

)

)

)

[Sales Red or Contoso - CROSSJOIN KEEPFILTERS] :=

CALCULATE (

[Sales Amount],

KEEPFILTERS (

FILTER (

CROSSJOIN (

ALL ( 'Product'[Color] ),

ALL ( 'Product'[Brand] )

),

'Product'[Color] = "Red" || 'Product'[Brand] = "Contoso"

)

)

)

SUMMARIZE函数会生成两个或多个列之间的现有组合列表,并且可以与不同表中的列一起使用,前提是它们在多对一关系链中连接起来。

[Sales Red or Contoso - SUMMARIZE filter] :=

CALCULATE (

[Sales Amount],

FILTER (

SUMMARIZE (

'Product',

'Product'[Color],

'Product'[Brand]

),

'Product'[Color] = "Red" || 'Product'[Brand] = "Contoso"

)

)

在这种情况下,与使用ALL/CROSSJOIN相比,筛选条件的基数被降低,但您需要付出表扫描的代价来获取在SUMMARIZE中指定的列的现有组合。对于大表中基数较低的列来说,这可能是一项昂贵的操作。对于复杂的筛选条件,它可能比表扫描更快,但就性能而言,您必须考虑在特定数据分布情况下替代的KEEPLFILTERS语法是否更好。

总结

您在CALCULATE语句中有多种选项来指定复杂的筛选条件。筛选参数的结果始终是一个具有一个或多个列的表,而筛选条件的"代价"就是您在这个表中的行数。筛选表通常是编写有效的复杂筛选表达式的"简单"方法,但它可能在FILTER迭代器中具有较大的粒度,并在CALCULATE中筛选条件本身的代价上有更高的成本,考虑到筛选参数中扩展表的相关成本。

您可以在《DAX权威指南》中找到有关内部行为和相关性能的更多详细信息。为了全面理解CALCULATE中表筛选和列筛选之间的差异以及其影响,我们建议阅读第10章《高级计算上下文》。

为了练习不同语法,您可以下载一个包含本文所述的计量应用于一个带有不同筛选器和切片器的数据透视表的Excel工作簿,以比较不同的结果。只有在较大的数据模型上才能体现出不同的性能差异。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有