4.5 處理多個表

處理多個表

既然您已經了解了評估上下文的基礎知識,我們就可以描述上下文在關系方面的行為。實際上,很少有數據模型僅包含一個表。最有可能存在通過關系鏈接的幾個表。如果SalesProduct之間存在關系,Product上的篩選上下文是否也篩選SalesSales表上的篩選呢?它篩選Product嗎?因為有兩種類型的評估上下文(行上下文和篩選上下文),并且關系具有兩個方面(一側和多側),所以要分析四種不同的情況。

這些問題的答案已存在于本章學到的那句口頭禪里了:“篩選上下文篩選;行上下文會迭代”,其效果是,“篩選上下文不會迭代;行上下文不會篩選。”

為了檢查場景,我們使用包含六個表的數據模型,如圖4-17所示。

圖4-17 用于學習上下文和關系之間的交互的數據模型

該模型有幾個值得注意的細節:

  • Sales到達Product Category,通過ProductProduct Subcategory,存在一系列的關系。
  • 唯一的雙向關系是SalesProduct之間的關系。所有其余關系都設置為單個交叉篩選方向。

在下一部分中查看評估上下文和關系的詳細信息時,該模型將非常有用。

行上下文和關系

行上下文進行迭代;它不會篩選。迭代是逐行掃描表并同時執行操作的過程。通常,人們想要某種匯總,例如總和或平均值。在迭代過程中,行上下文正在迭代單個表,它為表的所有列(僅該表)提供值。其他表盡管與迭代表有關,但在它們上沒有行上下文。換句話說,行上下文不會自動與關系交互。

Sales表中的一個計算列為例,該列包含實體表中存儲的單價與Product表中存儲的單價之差。以下DAX代碼不起作用,因為它使用Product [UnitPrice]列,并且Product上沒有行上下文:

Sales[UnitPriceVariance] = Sales[Unit Price] - 'Product'[Unit Price]

作為計算列,在包含該列的表(即Sales表)上DAX自動生成行上下文。Sales上的行上下文使用Sales中的列值對表達式逐行評估。即使ProductSales處于一對多關系的“一”側,該迭代僅發生在Sales表上。

當我們在關系的“多”方進行迭代時,我們可以在關系的一側訪問列,但是必須使用RELATED函數。RELATED接受列引用列作為參數,并檢索目標表中相應行中的列值。RELATED只能引用一列,并且需要多個RELATED函數才能在關系的一側訪問多個列。以前的代碼的正確版本如下:

Sales[UnitPriceVariance] = Sales[Unit Price] - RELATED ( 'Product'[Unit Price] )

RELATED要求在關系的“多”邊表上具有行上下文(即,迭代)。如果行上下文在關系的“一”側處于活動狀態,則RELATED將不再有用,因為RELATED將通過該關系找到多個行。在這種情況下,也就是說,當在關系的一側迭代時,要使用的函數是RELATEDTABLERELATEDTABLE返回與當前迭代表相關的多側表的所有行。例如,如果要計算每種產品的銷售數量,則將以下公式定義為Product上的計算列即可解決該問題:

Product[NumberOfSales] =
VAR SalesOfCurrentProduct = RELATEDTABLE ( Sales )
RETURN
    COUNTROWS ( SalesOfCurrentProduct )

此表達式計算Sales表中與當前產品相對應的行數。結果在圖4-18中可見。

圖4-18 RELATEDTABLE在關系的一側的行上下文中很有用

RELATEDRELATEDTABLE都可以遍歷關系鏈。它們不限于單跳。例如,可以使用與以前相同的代碼創建一列,但是這次,在Product Category表中:

'Product Category'[NumberOfSales] =
VAR SalesOfCurrentProductCategory = RELATEDTABLE ( Sales )
RETURN
    COUNTROWS ( SalesOfCurrentProductCategory )

結果是類別的銷售數量,該數量遍歷從“產品類別”到“產品子類別”,再到Product之間的關系鏈,最終到達Sales表。 以類似的方式,可以在Product表中創建一個計算列,該列從Product Category表中復制類別名稱。

'Product'[Category] = RELATED ( 'Product Category'[Category] )

在這種情況下,單個RELATED函數會遍歷從產品到產品子類別到產品類別的關系鏈。

注意
RELATEDRELATEDTABLE通用規則的唯一例外是一對一關系。如果兩個表共享一對一關系,則RELATEDRELATEDTABLE在兩個表中都起作用,并且根據使用的函數,它們將得出一個列值或具有單行的表。

關于關系鏈,所有關系都必須屬于同一類型,即一對多或多對一。如果鏈通過一對多關系將兩個表鏈接到一個橋接表,然后通過多對一關系鏈接到第二個表,則RELATEDRELATEDTABLE均不適用于單向篩選傳播。如后面所述,只有RELATEDTABLE可以使用雙向篩選。另一方面,一對一關系同時表現為一對多關系和多對一關系。因此,一對多(或多對一)鏈中可以存在一對一關系而不會中斷該鏈。

例如,在我們選擇作為參考的模型中,客戶與銷售有關,而銷售與產品有關。客戶與銷售之間存在一對多的關系,然后銷售與產品之間存在多對一的關系。因此,關系鏈將客戶與產品聯系起來。但是,兩個關系的方向不同。這種情況稱為多對多關系。客戶與購買的許多產品有關,而產品又與購買該產品的許多客戶有關。我們將在第15章“高級關系”中介紹多對多關系。現在,讓我們關注行上下文。如果一個人通過多對多關系使用RELATEDTABLE,那么結果將是錯誤的。考慮具有以下公式的 Product 中的計算列:

Product[NumOfBuyingCustomers] =
VAR CustomersOfCurrentProduct = RELATEDTABLE ( Customer )
RETURN
    COUNTROWS ( CustomersOfCurrentProduct )

先前代碼的結果不是購買該產品的客戶數量了。相反,結果是客戶總數,如圖4-19所示。

圖4-19 RELATEDTABLE不適用于多對多關系

RELATEDTABLE無法遵循關系鏈,因為它們的方向不同。產品的行上下文未到達客戶。值得注意的是,如果我們以相反的方向嘗試公式,即如果我們計算每個客戶購買的產品數量,則結果是正確的:每行代表客戶購買的產品數量的數字不同。此行為的原因不是行上下文的傳播,而是RELATEDTABLE生成的上下文轉換。我們添加了此最終注釋以進行全面披露。現在還沒有時間對此進行詳細說明。閱讀第5章后,您將對此有更好的理解。

篩選上下文和關系

在上一節中,您了解了行上下文是迭代的,因此,它不使用關系。另一方面,篩選上下文篩選。篩選上下文不會應用于單個表。相反,它始終適用于整個模型。在這一點上,您可以將評估上下文規范更新為完整的表述:

篩選上下文篩選模型;行上下文迭代一個表。

因為篩選上下文篩選模型,所以它使用關系。篩選上下文自動與關系交互,并且其行為取決于關系的交叉篩選方向的設置方式。交叉篩選的方向在關系的中間用小箭頭表示,如圖4-20所示。

圖4-20 篩選上下文和關系的行為

篩選上下文通過沿箭頭允許的方向使用關系。在所有關系中,箭頭允許從一側到多側傳播,而當交叉篩選方向為BOTH時,也允許從一側到多側傳播。

具有單向交叉篩選的關系是單向關系,而具有雙向交叉篩選的關系都是雙向關系。

此行為是直觀的。盡管我們沒有盡快對此進行解釋,但是到目前為止,我們使用的所有報告都依賴于此行為。確實,在典型的報告中,通過Product [Color]進行篩選并匯總Sales [Quantity],人們會期望把Product的篩選傳播到Sales。這正是發生的情況:產品處于關系的一側;因此,無論交叉篩選的方向如何,Product上的篩選都會傳播到Sales

因為我們的樣本數據模型同時包含雙向關系和許多單向關系,所以我們可以通過使用三種不同的度量值來演示篩選行為,這些度量值對三個表中的行數進行計數:SalesProductCustomer

[NumOfSales]:= COUNTROWS(銷售)
[NumOfProducts]:= COUNTROWS(產品)
[NumOfCustomers]:= COUNTROWS(客戶)

該報告在行上包含Product [Color]。因此,在篩選產品顏色的篩選上下文中評估每個單元格。結果如圖4-21所示。

圖4-21 顯示了篩選上下文和關系的行為

在第一個示例中,篩選始終從關系的一側傳播到多側。篩選從Product [Color]開始。從那里到達Sales表,ProductSales關系的多側。對于Product表,本身就是同一張表。另一方面,NumOfCustomers始終顯示相同的值,即客戶總數。這是因為客戶和銷售之間的關系不允許從銷售傳播到客戶。篩選從Product移動到Sales,但是從那里沒有到達Customers

您可能已經注意到,SalesProduct之間的關系是雙向關系。因此,Customer上的篩選器上下文也可以篩選SalesProduct。我們可以通過更改報告,按Customer[Education]而非Product[Color]進行切片來證明這一點。結果如圖4-22所示。

4-22 通過Customer[Education]進行篩選,Product表也被篩選

這次,篩選從Customer啟動。它可以到達Sales表,因為Sales在關系的多方面。此外,它從Sales傳播到Product,因為SalesProduct之間的關系是雙向關系,交叉篩選的方向是BOTH。

請注意,鏈中的單個雙向關系不會使整個鏈成為雙向的。實際上,一種類似的計算子類別數量的方法(例如下一項)表明,從Customer開始的篩選上下文未達到Product Subcategory

NumOfSubcategories := COUNTROWS ( 'Product Subcategory' )

將度量值添加到上一個報告中將產生如圖4-23所示的結果,其中所有行的NumOfSubcategories均相同。

DAX4-23.jpg

圖4-23 如果關系是單向的,則Customers無法篩選Product Subcategory

因為產品和產品子類別之間的關系是單向的,所以篩選不會傳播到產品子類別。如果我們更新關系,將交叉篩選的方向設置為BOTH,結果將有所不同,如圖4-24所示。

圖4-24 如果關系是雙向的,則*Customers*也可篩選*Product Subcategory*

對于行上下文,我們使用RELATEDRELATEDTABLE通過關系傳播行上下文。另一方面,對于篩選上下文,不需要任何功能來傳播篩選。篩選上下文篩選模型,而不是表。這樣一來,一旦應用了篩選上下文,整個模型就會根據這些關系接受篩選的處理。

重要
從這些示例來看,對所有關系啟用雙向篩選似乎是使篩選器上下文傳播到整個模型的一個不錯的選擇。絕對不是這樣。稍后,我們將在第15章中深入介紹高級關系。雙向篩選的復雜性比我們在本介紹性章節中分享的復雜得多,除非您對后果有一個清晰的認識,否則不要使用它們。通常,僅在嚴格要求時,才應使用CROSSFILTER函數以特定方式啟用雙向篩選。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。