DAX:GROUPBY函数
DAX 中的 SUMMARIZE 函数功能强大,但同时也很难使用,它可用于执行表之间的分组和连接。不幸的是,它在计算聚合值时存在一些众所周知的性能问题。除了性能之外,SUMMARIZE 的计算限制是它无法聚合在查询本身内动态计算的值。
一,SUMMARIZE函数的限制
例如,考虑以下查询,它应该为每个产品类别返回相关子类别的平均价格的最大值。
ADDCOLUMNS ( SUMMARIZE ( ADDCOLUMNS ( SUMMARIZE ( Product, 'Product Category'[Category], 'Product Subcategory'[Subcategory] ), "Average Price", CALCULATE ( AVERAGE ( Product[Unit Price] ) ) ), 'Product Category'[Category] ), "Max SubCat Avg Price", CALCULATE ( MAX ( [Average Price] ) ) )
如果运行此查询,计算 MAX ( [Average Price] ) 时会出现错误。 原因是在 DAX 中您只能聚合物理列(physical column)。 事实上,请记住这个等价物:
MAX ( table[expression] ) = MAXX ( table, table[expression] )
如果您尝试聚合在查询中计算的列(例如本例中的Average Price列),引擎将无法找到相应的 MAXX 函数,因此您会得到一个错误。 您可以通过重写查询避免嵌套的 SUMMARIZE 调用来获得所需的结果。
ADDCOLUMNS ( VALUES ( 'Product Category'[Category] ), "Max SubCat Avg Price", CALCULATE ( MAXX ( ADDCOLUMNS ( SUMMARIZE ( Product, 'Product Category'[Category], 'Product Subcategory'[Subcategory] ), "Average Price", CALCULATE ( AVERAGE ( Product[Unit Price] ) ) ), [Average Price] ) ) )
除了冗长之外,这种方法效率不高。 如果您想计算最低和最高平均价格,您将复制内部 SUMMARIZE,需要更长的执行时间。
二,引入GROUPBY函数
GROUPBY 函数的语法类似于 SUMMARIZE,尽管其语义不同。 事实上,它解决了我们在对值进行分组时在 SUMMARIZE 中遇到的问题,因此您可以避免本文中描述的模式 ADDCOLUMNS/SUMMARIZE 而只依赖 GROUPBY。
然而,即使使用 GROUPBY,您也不能使用我们在开始时看到的语法,因为聚合内部计算列的限制仍然存在。 您必须使用一个新函数 CURRENTGROUP,它允许访问内部组,因此您具有 aggX 函数的表参数,并且您可以通过行上下文以这种方式访问计算列。
注意:CURRENTGROUP ()函数只能用于GROUPBY 函数中。GROUPBY返回一组group,每个group有多个数据行(row),CURRENTGROUP ()函数用于从GROUPBY的结果中返回当前group。
GROUPBY ( ADDCOLUMNS ( GROUPBY ( Product, 'Product Category'[Category], 'Product Subcategory'[Subcategory] ), "Average Price", CALCULATE ( AVERAGE ( Product[Unit Price] ) ) ), 'Product Category'[Category], "Max SubCat Avg Price", MAXX ( CURRENTGROUP (), [Average Price] ) )
您必须在 GROUPBY 调用中使用 CURRENTGROUP,因此您不能使用ADDCOLUMNS 函数来添加新的计算列。仅当您在不使用 CALCULATE 或引用度量的情况下显式编写计算时,您才能摆脱 ADDCOLUMNS:这些操作在 GROUPBY 中是不允许的(目前唯一支持的用途是在聚合函数中调用 CURRENTGROUP),因此您仍然必须依赖 ADDCOLUMNS 以防您需要过滤上下文。 因此,您可以在不使用 ADDCOLUMNS 函数的情况下使用以下语法来计算平均价格列。
GROUPBY ( GROUPBY ( Product, 'Product Category'[Category], 'Product Subcategory'[Subcategory], "Average Price", AVERAGEX ( CURRENTGROUP() , Product[Unit Price] ) ), 'Product Category'[Category], "Max SubCat Avg Price", MAXX ( CURRENTGROUP (), [Average Price] ) )
结论:每当您想在迭代器中访问组的行时,您应该考虑使用 GROUPBY 而不是 ADDCOLUMNS/SUMMARIZE。 每当您有嵌套的分组操作时,这是必需的。 您可以在最里面的组中使用 SUMMARIZE,但必须使用 GROUPBY 才能访问在内部分组函数中计算的列。
参考文档: