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 才能訪問在內部分組函數中計算的列。
參考文檔: