Tableau 中建立計算的最佳做法
本文介紹在 Tableau 中建立高效計算的若干提示和準則。這些準則旨在協助您優化工作簿效能。有關可提高工作簿效能的所有方式的詳細資料,請參閱優化工作簿效能系列。
一般規則:避免在另一個計算中使用某個計算欄位多次
在另一個計算中引用同一計算欄位多次將導致效能問題。如果您在計算內使用計算欄位(也稱為建立巢狀計算),請嘗試只在計算中引用該計算欄位一次。
請注意,在計算中引用某個欄位(終端欄位)多次應該不會使效能降級。
範例
假設您建立一個計算欄位,該欄位使用複雜的多行計算在推文中尋找提及(或推特使用者名)。計算欄位名為 [Twitter Handle] (推特使用者名)。返回的每個使用者名以 [@] 符號開頭(例如:@user)。
為了便於分析,您想要移除 [@] 符號。
為此,您可以使用以下計算來從字串中移除第一個字元:
RIGHT([Twitter Handle], LEN([Twitter Handle]) -1)
此計算非常簡單。但是,由於它引用了 [Twitter Handle] (推特使用者名)計算兩次,因此會為資料來源中的每條記錄執行該計算兩次:一次針對 RIGHT 函數執行,另一次針對 LEN 函數執行。
為了避免計算同一個計算多次,您可以將計算改寫為只使用 [Twitter Handle] (推特使用者名)計算一次。在本例中,您可以使用 MID 來完成相同目標:
MID([Twitter Handle], 2)
提示 1:將多個等式比較轉換為 CASE 運算式或組
假設您有以下計算,該計算使用計算欄位 [Person (calc)] 多次,並使用一系列 OR 函數。此計算儘管是一個簡單的邏輯運算式,但會導致查詢效能問題,因為它會執行 [Person (calc)] 計算至少十次。
IF [Person (calc)] = 'Henry Wilson'
OR [Person (calc)] = 'Jane Johnson'
OR [Person (calc)] = 'Michelle Kim'
OR [Person (calc)] = 'Fred Suzuki'
OR [Person (calc)] = 'Alan Wang'
THEN 'Lead'
ELSEIF [Person (calc)] = 'Susan Nguyen'
OR [Person (calc)] = 'Laura Rodriguez'
OR [Person (calc)] = 'Ashley Garcia'
OR [Person (calc)] = 'Andrew Smith'
OR [Person (calc)] = 'Adam Davis'
THEN 'IC'
END
請嘗試以下解決方案,而不是使用等式比較。
解決方案 1
使用 CASE 運算式。例如:
CASE [Person (calc)]
WHEN 'Henry Wilson' THEN 'Lead'
WHEN 'Jane Johnson' THEN 'Lead'
WHEN 'Michelle Kim' THEN 'Lead'
WHEN 'Fred Suzuki' THEN 'Lead'
WHEN 'Alan Wang' THEN 'Lead'
WHEN 'Susan Nguyen' THEN 'IC'
WHEN 'Laura Rodriguez' THEN 'IC'
WHEN 'Ashley Garcia' THEN 'IC'
WHEN 'Andrew Smith' THEN 'IC'
WHEN 'Adam Davis' THEN 'IC'
END
在本例中,只引用了計算欄位 [Person (calc)] 一次。因此該計算也只會執行一次。CASE 運算式在查詢管道中還得到了進一步優化,因此效能得以額外提升。
解決方案 2
建立群組,而不是計算欄位。有關詳情,請參閱對資料進行分組。
提示 2:將多個字串計算轉換為單一 REGEXP 運算式
附註:REGEXP 計算僅在使用 Tableau 資料擷取或連線到文字檔、Hadoop Hive、Google BigQuery、PostgreSQL、Tableau 資料擷取、Microsoft Excel、Salesforce、Vertica、Pivotal Greenplum、Teradata(版本 14.1 及更高版本)和 Oracle 資料來源時可用。有關詳情,請參閱其他函數。
範例 1:CONTAINS
假設您有以下計算,該計算使用計算欄位 [Category (calc)] 多次。此計算儘管也是一個簡單的邏輯運算式,但會導致查詢效能問題,因為它會執行 [Category (calc)] 計算多次。
IF CONTAINS([Segment (calc)],'UNKNOWN')
OR CONTAINS([Segment (calc)],'LEADER')
OR CONTAINS([Segment (calc)],'ADVERTISING')
OR CONTAINS([Segment (calc)],'CLOSED')
OR CONTAINS([Segment (calc)],'COMPETITOR')
OR CONTAINS([Segment (calc)],'REPEAT')
THEN 'UNKNOWN'
ELSE [Segment (calc)] END
您可以使用 REGEXP 運算式來獲得同樣的結果,而不必進行同樣的重複。
解決方案
IF REGEXP_MATCH([Segment (calc)], 'UNKNOWN|LEADER|ADVERTISING|CLOSED|COMPETITOR|REPEAT') THEN 'UNKNOWN'
ELSE [Segment (calc)] END
對於使用類似模式的字串計算,您可以使用相同的 REGEXP 運算式。
範例 2:STARTSWITH
IF STARTSWITH([Segment (calc)],'UNKNOWN')
OR STARTSWITH([Segment (calc)],'LEADER')
OR STARTSWITH([Segment (calc)],'ADVERTISING')
OR STARTSWITH([Segment (calc)],'CLOSED')
OR STARTSWITH([Segment (calc)],'COMPETITOR')
OR STARTSWITH([Segment (calc)],'REPEAT')
THEN 'UNKNOWN'
解決方案
IF REGEXP_MATCH([Segment (calc)], '^(UNKNOWN|LEADER|ADVERTISING|CLOSED|COMPETITOR|REPEAT)') THEN 'UNKNOWN'
ELSE [Segment (calc)] END
請注意,此解決方案中使用 [^] 符號。
範例 3:ENDSWITH
IF ENDSWITH([Segment (calc)],'UNKNOWN')
OR ENDSWITH([Segment (calc)],'LEADER')
OR ENDSWITH([Segment (calc)],'ADVERTISING')
OR ENDSWITH([Segment (calc)],'CLOSED')
OR ENDSWITH([Segment (calc)],'COMPETITOR')
OR ENDSWITH([Segment (calc)],'REPEAT')
THEN 'UNKNOWN'
ELSE [Segment (calc)] END
解決方案
IF REGEXP_MATCH([Segment (calc)], '(UNKNOWN|LEADER|ADVERTISING|CLOSED|COMPETITOR|REPEAT)$') THEN 'UNKNOWN'
ELSE [Segment (calc)] END
請注意,此解決方案中使用 [$] 符號。
提示 3:使用 REGEXP(而不是 LEFT、MID、RIGHT、FIND、LEN)操作字串
規則運算式可能是一種非常強大的工具。在執行複雜的字串操作時,請考慮使用規則運算式。在許多情況下,使用規則運算式會使計算更加簡短高效。有關規則運算式的詳細資料,請參閱 Tableau 部落格上的 Become a regex regular and wrangle imperfect data(成為規則運算式精英並照管不完美的資料)(連結在新視窗開啟)博文。
範例 1
假設您有以下計算,該計算從 URL 中移除協定。例如: [https://www.tableau.com] 變為 [www.tableau.com] 。
IF (STARTSWITH([Server], "http://")) THEN
MID([Server], Len("http://") + 1)
ELSEIF(STARTSWITH([Server], "https://")) THEN
MID([Server], Len("https://") + 1)
ELSEIF(STARTSWITH([Server], "tcp:")) THEN
MID([Server], Len("tcp:") + 1)
ELSEIF(STARTSWITH([Server], "\\")) THEN
MID([Server], Len("\\") + 1)
ELSE [Server]
END
解決方案
可透過使用 REGEXP_REPLACE 函數來簡化計算和提高效能。
REGEXP_REPLACE([Server], "^(http://|https://|tcp:|\\\\)", "")
範例 2
假設您有以下計算,該計算返回 IPv4 位址的第二部分。例如: [172.16.0.1] 變為 [16] 。
IF (FINDNTH([Server], ".", 2) > 0) THEN
MID([Server],
FIND([Server], ".") + 1,
FINDNTH([Server], ".", 2) - FINDNTH([Server], ".", 1) - 1
)
END
解決方案
可透過使用 REGEXP_EXTRACT 函數來簡化計算和提高效能。
REGEXP_EXTRACT([Server], "\.([^\.]*)\.")
提示 4:不要在計算中使用集
如果在計算中使用集,請考慮將集替換為一個替代等效計算。
範例
假設您有以下計算,該計算使用集 [Top Customers (set)] 。
IF ISNULL([Customer Name]) OR [Top customers (set)] THEN [Segment] ELSE [Customer Name] END
解決方案 1
如果集很簡單,您可以建立一個其返回結果與集相同的計算欄位。例如:
CASE [Customer Name]
WHEN 'Henry Wilson' THEN True
WHEN 'Jane Johnson' THEN True
WHEN 'Michelle Kim' THEN True
WHEN 'Fred Suzuki' THEN True
WHEN 'Alan Wang' THEN True
ELSE False
END
附註:建議在此情況下使用模式 WHEN TRUE … ELSE,以避免由於使用集而導致的效能問題。大多數情況下不推薦使用該模式。
解決方案 2
如果集比較複雜,請考慮建立一個組,該組將集中的所有元素對應到一個給定的值或屬性(例如 [IN] ),然後修改計算來檢查該值/屬性。例如:
IF ISNULL([Customer Name]) OR [Top Customers(group)]='IN' THEN [Segment] ELSE [Customer Name] END
提示 5:不要使用集對資料進行分組
集旨在對資料的子集進行比較。組旨在將相關成員合併在一個欄位中。不推薦將集轉換為群組,例如透過以下範例進行轉換:
IF [Americas Set] THEN "Americas"
ELSEIF [Africa Set] THEN "Africa"
ELSEIF [Asia Set] THEN "Asia"
ELSEIF [Europe Set] THEN "Europe"
ELSEIF [Oceania Set] THEN "Oceania"
ELSE "Unknown"
END
之所以不推薦這樣做,有以下幾個原因:
集並不始終是排他的。某些成員可能會出現在多個集中。例如, [俄羅斯] 既可能放在 [歐洲] 集中,也可能放在 [亞洲] 集中。
集並不會始終轉換為群組。如果集是透過排除、條件或限制定義的,則可能很難甚至無法建立等效的組。
解決方案
使用 [群組] 功能對資料進行分組。有關詳情,請參閱對資料進行分組。