過濾器函式允許你操縱篩選上下文以建立動態的計算,是DAX中最複雜和最強大的一類函式,本文記錄我對一些常見的過濾器函式的總結。
一,篩選上下文的構成
DAX中的篩選上下文由三部分構成:交叉過濾構成的過濾,查詢上下文中每行的列值構成的過濾,外部切片器構成的顯式過濾。
1,交叉過濾器
在資料模型中建立關係,指定交叉過濾器
2,查詢上下文
在當前查詢的上下文中,每行的列值也會作為過濾器,例如,ProductCategoryName和Color是當前查詢上下文的行過濾器:
3,外部切片器
在報表中設定的切片器,是在查詢上下文外部的設定的過濾器,例如,上圖中的Color切片器就是外部切片器。
二,清除過濾器
ALL系列的函式能夠清除已經應用的過濾器。
1,ALL
ALL 函式返回表中的所有行,或者一列的所有值,忽略可能已經應用的任何過濾器。此函式用於清除過濾器,對錶中的所有行進行計算。注意,此函式只能用於基礎表(base table),不能用於表表示式或列表示式。
ALL( [<table> | <column>[, <column>[, <column>[,…]]]] )
2,ALLCROSSFILTERED
ALLCROSSFILTERED函式用於清除應用到表上的所有過濾器,該函式不返回任何值,僅僅用於清除表上的過濾器。
ALLCROSSFILTERED(<table>)
例如,計算FactInternetSales表上所有OrderQuantity的值:
= CALCULATE(SUM(FactInternetSales[OrderQuantity]), ALLCROSSFILTERED(FactInternetSales))
3,ALLEXCEPT
ALLEXCEPT函式用於移除其他欄位的所有過濾器,而保留引數指定的欄位上的過濾器,
ALLEXCEPT(<table>,<column>[,<column>[,…]])
返回一個表,除了引數指定的欄位上的過濾器之外,其他欄位的過濾器都被移除,例如,保留 DateTime[CalendarYear] 欄位上的過濾器,表DateTime中其他欄位的過濾器都被移除:
= CALCULATE(SUM(ResellerSales_USD[SalesAmount_USD]), ALLEXCEPT(DateTime, DateTime[CalendarYear]))
4,ALLSELECTED
ALLSELECTED 的作用是從當前查詢的上下文中移除的行和列的過濾(即忽略行和列的過濾),而保留當前查詢除行和列之外的上下文過濾器或顯式定義的過濾器(例如切片器等):
ALLSELECTED([<table> | <column>[, <column>[, <column>[,…]]]] )
引數table和column是可選的,如果有多個column引數,那麼這些column必須來自同一個table。返回值是不包括行和列過濾器的查詢上下文。
例如,計算選定的顏色和分類的產品銷售數量的佔比。在報表中設定切片器,共選擇了4種顏色,這是報表顯式定義的過濾器。
- 當前查詢的上下文過濾器是由ProductCategory和Color,以及外部的切片器構成的;
- 分母的計算邏輯是移除當前查詢的上下文過濾器,也就是不管產品ProductCategory和Color,計算4種Color(外部切片器決定)對應的產品銷售的總量,四種顏色對應的SalesAmount總量是12944190.35。
- 分子的計算邏輯是在當前查詢的上下文中,計算特定的ProductCategory和Color的產品銷售的數量。例如,顏色為Red的Bikes的銷售總量是7646302.82,除以SalesAmount總量12944190.35,約等於0.59。
SalesRateBySelectedColors = DIVIDE(CALCULATE(SUM( FactSales[SalesAmount]))*1.0, CALCULATE(SUM(FactSales[SalesAmount]),ALLSELECTED()))
三,顯式過濾
在DAX中對錶進行過濾,用於在表示式中增加過濾器:
FILTER(<table>,<filter>)
引數是布林表示式,用於逐行執行,對錶進行過濾,返回結果為True的行,而把結果位False的行移除,例如:
FILTER(FactSales, [Amount] > 0 or [Region] = "France")
四,直接過濾和交叉過濾
資料模型中的過濾分為直接過濾和交叉過濾:
直接過濾:當過濾直接作用到表中的列col上時,列col是被直接過濾的。直接過濾是由外部的切片器和查詢上下文中的行和列過濾器確定的,不受交叉過濾器的影響。
注意:如果外部切片器沒有勾選任何選項時,預設顯示基礎表中所有的唯一值。
交叉過濾:當過濾作用於同一個表的另一列B上,或作用於相關表上時,列A是被交叉過濾的,交叉過濾收到所有篩選上下文的影響。
direct_filtered_colors = COUNTROWS((FILTERS(DimProduct[Color]))) cross_filtered_distinct_colors = COUNTROWS((DISTINCT(DimProduct[Color]))) cross_filtered_values_colors = COUNTROWS((VALUES(DimProduct[Color])))
結果分析:
direct_filtered_colors:是直接過濾,不受交叉過濾上下文的影響,直接顯式基礎表中Color的唯一值的數量,
cross_filtered_values_colors 和 cross_filtered_distinct_colors :是交叉過濾,受到交叉過濾上下文的影響,只統計被過濾之後的Color的數量。
1,判斷是直接過濾還是交叉過濾
直接過濾和交叉過濾可以通過函式來識別:
ISCROSSFILTERED(<columnName>)
ISFILTERED(<columnName>)
2,返回過濾的唯一值
移除重複,只保留唯一值,當返回直接過濾的唯一值時,使用FILTERS()函式:
FILTERS(<columnName>)
當返回交叉過濾的唯一值時,使用DISTINCT 和 VALUES函式,這兩個函式都受到過濾上下文的作用。唯一的區別是:
當原始表中不存在BLANK時,DISTINCT 只返回原始表中的值,而VALUES可能會返回BLANK,該資料是被新增到查詢中用於表示不相關的行。
DISTINCT 和 VALUES函式的定義是:
DISTINCT(<table | column>)
VALUES(<Table | Column>)
3,檢查唯一
當直接過濾的唯一值只有一個時,返回True;否則返回False。
HASONEFILTER(<columnName>)
該函式等價於:
COUNTROWS(FILTERS(<columnName>)) = 1
當列上下文中只有一個唯一值時,返回True;否則,返回False
HASONEVALUE(<columnName>)
該函式等價於:
COUNTROWS(VALUES(<columnName>)) = 1
4,SELECTEDVALUE
當column的上下文被過濾為只有一個唯一值時,返回該唯一值,否則返回alternateResult。
SELECTEDVALUE(<column>[, <alternateResult>])
該函式等價於:
IF(HASONEVALUE(<column>), VALUES(<column>), <alternateResult>)
五,關聯值
關聯需要當前表和關聯表之間存在關係。跟當前行相關的唯一值,該函式不受任何過濾器的影響:
RELATED(<column>)
RELATED函式需要當前表和關聯表之間存在關係,在函式中指定包含你需要資料的列,該函式遵循現有的多對一關係,以從相關表的指定列中獲取一個值,也就是說,RELATED函式從多方關聯到1方的一個值,引數column是1方表中的列。當RELATED函式執行查詢時,它會檢查指定表中的所有值,而不管可能已應用的任何過濾器。
注意:RELATED函式需要行上下文,因此,只能用於計算列表示式中(其當前行上下文是明確的) 和表掃描函式中。表掃描函式(如SUMX)獲取當前行的值,然後掃描關聯表以查詢指定列的關聯值。
例如,從下圖中可以看到,FactSales和DimProduct之間存在 “*對1” 的關係,並且FactSales是多方,DimProduct是1方。可以在RELATED()函式中指定DimProduct表中的列,以從DimProduct表獲得跟FactSales中某一行相關聯的值。
在FactSales表中建立計算列,獲取跟當前行相關的產品顏色的值:
Related_color = RELATED( DimProduct[Color])
參考文件: