DAX有三個用於生成分組聚合數據的函數,這三個函數有兩個共同的特征:分組列和擴展列。
- 分組列是用於分組的列,只能來源於基礎表中已存的列,分組列可以來源於同一個表,也可以來源於相關的列。
- 擴展列是由name和expression對構成的,name是字符串,expression是包含聚合函數的表達式。
在分組列和擴展列上,這三個函數有各自獨特的處理方式。
一,SUMMARIZE
SUMMARIZE函數對相互關聯的Table按照特定的一個字段(分組列)或多個字段,進行分組聚合。由於分組列是唯一的,通過SUMMARIZE函數,可以獲得多列的唯一值構成的二維表:
SUMMARIZE(<table>, <groupBy_columnName>[, <groupBy_columnName>]…[, <name>, <expression>]…)
參數注釋:
- table:必需參數,表示主表,可以是任何返回表的表達式。
- groupBy_columnName:可選參數,表示分組列,該列必須是table參數中的列,或者相關聯表中的列。分組列必須使用列的完全限定名,格式是table[column],分組列可以有0個,1個或多個。
- name、expression:可選參數,表示自定義的匯總列/擴展列,該參數對總是成對出現的,name是expression計算結果的名稱,expression用於計算列的聚合值。
該函數的返回值是一個匯總表,匯總表包含分組列和自定義的擴展列。
1,獲得多列的唯一值
分組列是唯一的,可以不返回匯總列,而只返回分組列,這樣得到的表是多列的唯一值。
SUMMARIZE(ResellerSales
, DateTime[CalendarYear]
, ProductCategory[ProductCategoryName]
)
2,獲得匯總數據
例如,對數據表 ResellerSales ,按照字段 DateTime[CalendarYear] 和 ProductCategory[ProductCategoryName]分組,計算 ResellerSales[SalesAmount]和 ResellerSales[DiscountAmount]的加和 。
SUMMARIZE(ResellerSales
, DateTime[CalendarYear]
, ProductCategory[ProductCategoryName]
, "Sales Amount", SUM(ResellerSales[SalesAmount]) , "Discount Amount", SUM(ResellerSales[DiscountAmount]) )
該函數利用ResellerSales和DateTime、ProductCategory之間的關系,得到關聯表數據(是一個中間臨時表),按照DateTime[CalendarYear] 和 ProductCategory[ProductCategoryName] 對關聯之后的數據進行分組,分別計算銷售和折扣的加和。
注意,ResellerSales和DateTime,ResellerSales和ProductCategory 必須顯式存在關系,否則,不能用於分組列中。
3,分組聚合的作用
第一是作為中間臨時表,為后續的計算提供數據;第二是用於創建新表,在Modeling菜單中,通過“New Table”從DAX表達式中創建新的Table:

參考文檔:SUMMARIZE – groupping in data models (DAX – Power Pivot, Power BI)
4,ROLLUP選項
ROLLUP函數用於對分組列進行上卷操作,該函數用於預定義多個分組集:
SUMMARIZE(<table>, <groupBy_columnName>[, <groupBy_columnName>]…[, ROLLUP(<groupBy_columnName>[,< groupBy_columnName>…])][, <name>, <expression>]…)
作用類似於TSQL的 rollup函數,例如,對於group by rollup(a,b) ,其表示的分組集是group by (), group by (a), group by (a,b)。
5,ROLLUPGROUP選項
ROLLUPGROUP函數用於計算小計組。如果把ROLLUPGROUP來代替ROLLUP函數,那么ROLLUPGROUP通過向groupBy_columnName列的結果添加匯總行來產生和ROLLUP相同的結果。 但是,在ROLLUP語法中添加ROLLUPGROUP()可用於防止匯總行中的部分小計。例如,ROLLUP(ROLLUPGROUP(A,B)),分組集是(A,B)和():
SUMMARIZE(ResellerSales_USD , ROLLUP(ROLLUPGROUP( DateTime[CalendarYear], ProductCategory[ProductCategoryName])) , "Sales Amount (USD)", SUM(ResellerSales_USD[SalesAmount_USD]) , "Discount Amount (USD)", SUM(ResellerSales_USD[DiscountAmount]) )
6,ISSUBTOTAL選項
只能用於SUMMRIZE函數中,用於檢查該列是否為小計組。
SUMMARIZE(<table>, <groupBy_columnName>[, <groupBy_columnName>]…[, ROLLUP(<groupBy_columnName>[,< groupBy_columnName>…])][, <name>, {<expression>|ISSUBTOTAL(<columnName>)}]…)
例如,使用該函數檢查CalendarYear和 ProductCategoryName是否為小計組:
SUMMARIZE(ResellerSales_USD , ROLLUP( DateTime[CalendarYear], ProductCategory[ProductCategoryName]) , "Sales Amount (USD)", SUM(ResellerSales_USD[SalesAmount_USD]) , "Discount Amount (USD)", SUM(ResellerSales_USD[DiscountAmount]) , "Is Sub Total for DateTimeCalendarYear", ISSUBTOTAL(DateTime[CalendarYear]) , "Is Sub Total for ProductCategoryName", ISSUBTOTAL(ProductCategory[ProductCategoryName]) )
二,SUMMARIZECOLUMNS
該函數也用於分組聚合,和SUMMARIZE函數的差異在於分組列之間的關系是非必需的,分組列之間執行的交叉連接或自動存在。
SUMMARIZECOLUMNS( <groupBy_columnName> [, < groupBy_columnName >]…, [<filterTable>]…[, <name>, <expression>]…)
參數注釋:
- groupBy_columnName:分組列,該列必須使用列的完全限定名,格式是base_table[column],該列必須是基礎表中的現存列,分組列可以有0個,1個或多個。多個分組列之間的表不要求必須有關系,對於不同表,分組列之間是交叉連接(cross-join);對於相同表,分組列之間使用的是自動存在(auto-existed)。
- filterTable:可選參數,對分組列所在的基礎表進行過濾, 過濾器表中存在的值用於在執行交叉連接/自動存在之前進行過濾。
- name、expression:可選參數,表示自定義的匯總列,該參數對總是成對出現的,name是expression計算結果的名稱,expression用於計算列的聚合值。
返回值是匯總表,包含分組列和自定義列,返回的數據行中,至少包含一個非空值,如果在一個數據行中,所有expression的結果都是BLANK/NULL,那么該行不包含在匯總表中。
1,分組字段進行笛卡爾乘積
以下DAX按照SalesTerritory的字段Category 和 Customer的Education字段進行分組,並對Customer表進行過濾:
SUMMARIZECOLUMNS ( 'SalesTerritory'[Category], 'Customer' [Education], FILTER('Customer', 'Customer'[First Name] = “Alicia”) )
對過濾之后的數據進行匯總計算,返回的結果是Category和Eduction的笛卡爾乘積。
2,IGNORE選項
把包含NULL/BLANK的行過濾掉
SUMMARIZECOLUMNS(<groupBy_columnName>[, < groupBy_columnName >]…, [<filterTable>]…[, <name>, IGNORE(…)]…)
例如,如果Sum(Sales[Qty] )中包含一個NULL/BLANK,那么把該行從結果集中移除:
SUMMARIZECOLUMNS( Sales[CustomerId], "Total Qty", IGNORE( SUM( Sales[Qty] ) ), “BlankIfTotalQtyIsNot3”, IF( SUM( Sales[Qty] )=3, 3 ) )
3,其他選項
- NONVISUAL()
- ROLLUPADDISSUBTOTAL()
- ROLLUPGROUP()
三,GROUPBY
GROUPBY函數除了不能再擴展列中使用CALCULATE函數之外,和SUMMARIZE的用法相同:
GROUPBY (<table>, [<groupBy_columnName1>]..., [<name>, <expression>]… )
expression參數中不能使用CALCULATE函數,CURRENTGROUP 函數只能用於最頂層的表掃描(Table Scan)操作。
GROUPBY函數執行的操作是:
- #1:從指定的表(以及“to-one”方向的所有相關表)開始
- #2:按照所有的GroupBy列創建分組,每一個分組代表一組數據行
- #3:對於每一個分組,評估要增加的擴展列(Extension column)。與SUMMARIZE函數不同,不執行隱含的CALCULATE,並且不把該組放入到過濾器上下文中。
在該函數中,可以調用CURRENTGROUP 函數:
CURRENTGROUP()
該函數只能用於GROUPBY函數的expression參數中,表示當前分組。 CURRENTGROUP函數不帶參數,僅支持作為以下聚合函數之一的第一個參數:AverageX,CountAX,CountX,GeoMeanX,MaxX,MinX,ProductX,StDevX.S,StDevX.P,SumX,VarX.S,VarX.P。舉個例子,對Sales表,按照Country和Category進行分組,計算每個分組中Price * Qty的乘積之和。
GROUPBY ( Sales, Geography[Country], Product[Category], “Total Sales”, SUMX( CURRENTGROUP(), Sales[Price] * Sales[Qty]) )
參考文檔:
