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 才能访问在内部分组函数中计算的列。

 

参考文档:

Nested grouping using GROUPBY vs SUMMARIZE

posted @ 2022-12-09 11:20  悦光阴  阅读(743)  评论(0编辑  收藏  举报