DAX 第三篇:過濾器函式

悅光陰發表於2019-07-23

過濾器函式允許你操縱篩選上下文以建立動態的計算,是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]) 

 

 

參考文件:

Filter functions

allselected()函式

相關文章