tableau的高級計算


Tableau的高級計算是通過計算字段來完成的。

計算字段的本質是通過表達式,基於數據源中已有的數據創建數據源中不存在的數據。

計算字段分類

計算字段分為以下幾類:

  • Basic calculations:數據源級別((a row-level calculation))或者可視化級別(an aggregate calculation)
  • Level of Detail (LOD) expressions : 可以更加精細和自由地控制聚合的粒度。LOD calculations give you even more control on the level of granularity you want to compute. They can be performed at a more granular level (INCLUDE), a less granular level (EXCLUDE), or an entirely independent level (FIXED) with respect to the granularity of the visualization.
  • Table calculations:在圖表上進行計算。

計算字段的表達式,可以引用已經存在的計算表達式,構成復雜的計算。

另外,Tableau的計算表達式中使用的函數是Tableau內置的,與數據源無關。在生成sql的時候,Tableau會把tab 函數翻譯成對應數據源的函數。

比如:

ZN([price])-ZN([shipping_cost])

在mysql數據源中將翻譯成:

IFNULL(company_sales_record.price, 0) - IFNULL(company_sales_record.shipping_cost, 0)

基礎計算字段

基礎計算字段分為聚合型和非聚合型,非聚合型計算字段就是在數據源表的每一行內的不同字段之間做計算,計算不能帶聚合函數。聚合型計算字段帶聚合函數,以圖表中的維度作為分組依據。

LOD

LOD的語法是包含在大括號里的表達式,分成維度組,聚合表達式兩部分,用冒號分割。其中維度組有個粒度控制符關鍵字,標明表達式的維度組合與圖表中維度的關系。lod的語法定義如下:

{[FIXED | INCLUDE | EXCLUDE] <維度聲明> : <聚合表達式>}

粒度控制關鍵字

FIXED

FIXED 詳細級別表達式使用指定的維度做聚合計算,而不引用圖表中的任何其他維度。它還會忽略除上下文篩選器、數據源篩選器和數據提取篩選器之外的所有篩選器。

在需要固定值、與圖表無關的聚合值時(因為聚合與圖表無關,因此可以當成維度使用),fixed非常有用。

比如:

{ FIXED [Region] : SUM([Sales]) }

它會僅以Region作為分組維度做聚合。

INCLUDE

INCLUDE除了圖表中的維度之外,還會將表達式中維度一起作為分組的一句。當需要納入不在圖表中的維度做聚合時,INCLUDE 詳細級別表達式最有用。使用include可以讓度量做二次聚合。

比如

{ INCLUDE [Customer Name] : SUM([Sales]) }

它總是會將Customer Name和圖表中的其他維度放到一起作為分組依據,使聚合的粒度比圖表更細。

EXCLUDE

EXCLUDE 詳細級別表達式從表達式中顯式移除維度,也就是說,這些表達式從圖表詳細級別中去除維度,在比圖表中更粗粒度完成聚合。在需要總計、小計值時,exclude非常有用。

比如:

{EXCLUDE [Region]: SUM([Sales])}

它將Region排除,不作為聚合的分組依據。

全表范圍

全表范圍對於表范圍詳細級別表達式,不需要定界關鍵字,表示對整整表全局做聚合,代表“總計”的概念。

和過濾器的關系

過濾器分為以下幾類

Extract Filters:數據源級別的過濾器,是最高優先級的,可以看成是ETL提取。

Data Source Filters :數據源級別的過濾器,直接作用在數據源上。

Context Filters:上下文過濾器,可以理解為數據集級別過濾器。

Dimension Filters:維度過濾器,相當於查詢sql里的where

Measure Filters:度量過濾器,相當於查詢sql里的having

Table CalcPlan Filters:圖表過濾器,只影響圖表的展示,不影響數據處理。

lod受過濾的影響如下:

可以看到,不會忽略的過濾器有context filters, data source filters, and extract filters,這些過濾器一定會影響LOD的計算

參考:

https://help.tableau.com/current/pro/desktop/en-us/calculations_calculatedfields_lod_overview.htm#filters-and-level-of-detail-expressions

https://help.tableau.com/current/pro/desktop/en-us/order_of_operations.htm

表達式結果類型

Fixed 的lod可以是度量也可以是維度(取決於所計算的字段),include和exclude的lod只能是度量

和圖表聚合的關系

比圖表維度更粗粒度的聚合:重復。這種情況下,圖表指標上的聚合方式是無效的。
比圖表維度更細粒度的聚合:再聚合。這種情況下,圖表上的聚合方式會嵌套在lod的聚合之上。
和圖表維度同粒度的聚合:什么都不做。這種情況下,聚合已經在寫lod的時候寫了額,因此圖表指標上的聚合方式也是無效的。

  • INCLUDE level of detail expressions will have either the same level of detail as the view or a finer level of detail than the view. Therefore, values will never be replicated.
  • FIXED level of detail expressions can have a finer level of detail than the view, a coarser level of detail, or the same level of detail. The need to aggregate the results of a FIXED level of detail depends on what dimensions are in the view.
  • EXCLUDE level of detail expressions always cause replicated values to appear in the view. When calculations including EXCLUDE level of detail expressions are placed on a shelf, Tableau defaults to the ATTR aggregation (as opposed to SUM or AVG) to indicate that the expression is not actually being aggregated and that changing the aggregation will have no effect on the view.

在寫lod的時候,也可以顯式的在外面套上聚合函數,這時候拖入圖表中,如果需要聚合的話,聚合方式就是你顯式寫的那個,不需要聚合的話,這個聚合會被忽略掉。

LOD總結

LOD的本質是實現數據的多層處理,外層的處理是在里層的結果之上進行的,或者說外出處理的對象是里層處理的結果,里層處理結果是中間結果。因此,LOD是具備一定的ETL能力的。

表計算

表計算只能對圖表內的數據進行計算,不考慮圖表以外的任何數據。從下圖的執行優先級也可以看出,表計算是排在measure Filter之后執行的。

重要概念

分區:用於確定計算的范圍,計算只在分區內進行,不同分區的計算是單獨進行的。
尋址:決定了計算的方向。 如果有多個維度,則是根據維度的順序,先穿越后面的維度,再穿越前面的維度。
在表計算面板中,選中的所有維度都是尋址維度,剩下的是分區維度。

相對於:在對比型的表計算中,還有一個重要的概念叫“相對於”,由它在尋址方向上確定對比數據的具體位置。通常有:前一個、后一個、第一個、最后一個。


表計算的類型

差值:計算差值對比,屬於對比型計算

差值百分比:計算差值的百分比,屬於對比型計算

百分位比:計算當前數據與對比數據的比值,屬於對比型計算

占比:計算當前數據與小計數據的比值。

排名:計算組內排名,屬於值轉化型計算

百分位數:將數值規划到0~100%之間,屬於值轉化型計算

累計計算:滑動求組內累計值

滑動計算:窗口滑動計算窗口內的值

注意,表計算也是可以嵌套的,通過添加二次計算實現,比如計算累計值的年對比。

參考:https://help.tableau.com/current/pro/desktop/en-us/calculations_tablecalculations_definebasic_runningtotal.htm#percent-of-total-calculation

SELECT
	(
		(
			TO_DAYS(
				ADDDATE(
					DATE_FORMAT( `company_sales_record`.`report_date`, '%Y-%m-%d 00:00:00' ),
					INTERVAL 0 SECOND 
				) 
				) - TO_DAYS(
				ADDDATE(
					DATE_FORMAT( `t0`.`__measure__0`, '%Y-%m-%d 00:00:00' ),
					INTERVAL 0 SECOND 
				) 
			) 
			) + (
			TIME_TO_SEC(
				ADDDATE(
					ADDDATE(
						DATE_FORMAT( `company_sales_record`.`report_date`, '%Y-%m-%d 00:00:00' ),
						INTERVAL 0 SECOND 
					),
					INTERVAL 0 SECOND 
				) 
				) - TIME_TO_SEC(
				ADDDATE(
					ADDDATE(
						DATE_FORMAT( `t0`.`__measure__0`, '%Y-%m-%d 00:00:00' ),
						INTERVAL 0 SECOND 
					),
					INTERVAL 0 SECOND 
				) 
			) 
		) / ( 60 * 60 * 24 ) 
	) AS `Calculation_505036481761304585`,
	`company_sales_record`.`customer_name` AS `customer_name` 
FROM
	`company_sales_record`
	INNER JOIN (
	SELECT
		`company_sales_record`.`customer_name` AS `customer_name`,
		MIN( `company_sales_record`.`report_date` ) AS `__measure__0` 
	FROM
		`company_sales_record` 
	GROUP BY
		1 
	) `t0` ON ( `company_sales_record`.`customer_name` <=> `t0`.`customer_name` ) 
GROUP BY
	1,
	2

不同類型計算字段的使用場景


1.圖表里是否已經有需要的數據,如果有,就用表計算,否則用普通計算字段或者LOD。

2.需要的數據的是否是非聚合,還是聚合粒度恰好和圖表里的聚合粒度一致?

參考:

https://www.tableau.com/about/blog/2016/4/guide-choosing-right-calculation-your-question-53667?_ga=2.179589668.1614904189.1628168106-580442927.1628168103

其他

Tableau沒有辦法直接處理時間上的計算比如同環比等等,只能依賴表計算,參考:http://www.raiahmad.com/time-intelligence-functions-in-tableau/

附錄

度量轉維度示例

求銷售額的年累計Days Since First Day 默認是一個度量,但是當把它拖入圖表是,可以把它轉成維度使用。如果我們把它轉成維度,統計不同間隔天數的購買行為的平均銷售額。

生成的SQL如下:

SELECT
	(
		(
			TO_DAYS(
				ADDDATE(
					DATE_FORMAT( `company_sales_record`.`report_date`, '%Y-%m-%d 00:00:00' ),
					INTERVAL 0 SECOND 
				) 
				) - TO_DAYS(
				ADDDATE(
					DATE_FORMAT( `t0`.`__measure__0`, '%Y-%m-%d 00:00:00' ),
					INTERVAL 0 SECOND 
				) 
			) 
			) + (
			TIME_TO_SEC(
				ADDDATE(
					ADDDATE(
						DATE_FORMAT( `company_sales_record`.`report_date`, '%Y-%m-%d 00:00:00' ),
						INTERVAL 0 SECOND 
					),
					INTERVAL 0 SECOND 
				) 
				) - TIME_TO_SEC(
				ADDDATE(
					ADDDATE(
						DATE_FORMAT( `t0`.`__measure__0`, '%Y-%m-%d 00:00:00' ),
						INTERVAL 0 SECOND 
					),
					INTERVAL 0 SECOND 
				) 
			) 
		) / ( 60 * 60 * 24 ) 
	) AS `Calculation_505036481761304585`,
	AVG( `company_sales_record`.`price` ) AS `avg_price_ok` 
FROM
	`company_sales_record`
	INNER JOIN (
	SELECT
		`company_sales_record`.`customer_name` AS `customer_name`,
		MIN( `company_sales_record`.`report_date` ) AS `__measure__0` 
	FROM
		`company_sales_record` 
	GROUP BY
		1 
	) `t0` ON ( `company_sales_record`.`customer_name` <=> `t0`.`customer_name` ) 
GROUP BY
	1

如果加上時間維度作為顏色,還能對不不同時間段內的銷售數據。

聚合的聚合

假設要計算每個用戶的銷售額,並且兼顧圖表上的維度,創建計算字段SalesPerCustomer

{INCLUDE [customer_name]:SUM([price])}

在圖表上使用這個計算字段,選擇avg聚合,並且拖入area維度。此時計算的結果是:在各區域內人均消費額。

它涉及到兩層聚合,第一層是在[area],[customer_name]上對price做sum聚合,第二層是在[area]上對第一層的結果做avg聚合。

它生產的SQL如下

SELECT
	`t0`.`area` AS `area`,
	AVG( `t0`.`__measure__1` ) AS `avg_Calculation_715016814507118592_ok` 
FROM
	(
	SELECT
		`company_sales_record`.`area` AS `area`,
		SUM( `company_sales_record`.`price` ) AS `__measure__1` 
	FROM
		`company_sales_record` 
	GROUP BY
		1,
		`company_sales_record`.`customer_name` 
	) `t0` 
GROUP BY
	1

非聚合計算字段嵌套LOD示例

要求:用戶每次購買時間相對於第一次購買時間的間隔天數

先創建LOD計算字段 First Purchase Date

{FIXED [Customer Name] : MIN([report_dateOrder Date])}

再創建非聚合計算字段Days Since First Day,它引用了前一個計算字段First Purchase Date

DATETRUNC('day', [report_date])-DATETRUNC('day', [First Purchase Date])

對Days Since First Day執行明細查詢,生成的SQL如下

SELECT
	(
		(
			TO_DAYS(
				ADDDATE(
					DATE_FORMAT( `company_sales_record`.`report_date`, '%Y-%m-%d 00:00:00' ),
					INTERVAL 0 SECOND 
				) 
				) - TO_DAYS(
				ADDDATE(
					DATE_FORMAT( `t0`.`__measure__0`, '%Y-%m-%d 00:00:00' ),
					INTERVAL 0 SECOND 
				) 
			) 
			) + (
			TIME_TO_SEC(
				ADDDATE(
					ADDDATE(
						DATE_FORMAT( `company_sales_record`.`report_date`, '%Y-%m-%d 00:00:00' ),
						INTERVAL 0 SECOND 
					),
					INTERVAL 0 SECOND 
				) 
				) - TIME_TO_SEC(
				ADDDATE(
					ADDDATE(
						DATE_FORMAT( `t0`.`__measure__0`, '%Y-%m-%d 00:00:00' ),
						INTERVAL 0 SECOND 
					),
					INTERVAL 0 SECOND 
				) 
			) 
		) / ( 60 * 60 * 24 ) 
	) AS `Calculation_505036481761304585`,
	`company_sales_record`.`customer_name` AS `customer_name` 
FROM
	`company_sales_record`
	INNER JOIN (
	SELECT
		`company_sales_record`.`customer_name` AS `customer_name`,
		MIN( `company_sales_record`.`report_date` ) AS `__measure__0` 
	FROM
		`company_sales_record` 
	GROUP BY
		1 
	) `t0` ON ( `company_sales_record`.`customer_name` <=> `t0`.`customer_name` ) 
GROUP BY
	1,
	2

對Days Since First Day求平均值,生成的SQL如下

SELECT
	AVG(
		(
			(
				TO_DAYS(
					ADDDATE(
						DATE_FORMAT( `company_sales_record`.`report_date`, '%Y-%m-%d 00:00:00' ),
						INTERVAL 0 SECOND 
					) 
					) - TO_DAYS(
					ADDDATE(
						DATE_FORMAT( `t0`.`__measure__0`, '%Y-%m-%d 00:00:00' ),
						INTERVAL 0 SECOND 
					) 
				) 
				) + (
				TIME_TO_SEC(
					ADDDATE(
						ADDDATE(
							DATE_FORMAT( `company_sales_record`.`report_date`, '%Y-%m-%d 00:00:00' ),
							INTERVAL 0 SECOND 
						),
						INTERVAL 0 SECOND 
					) 
					) - TIME_TO_SEC(
					ADDDATE(
						ADDDATE(
							DATE_FORMAT( `t0`.`__measure__0`, '%Y-%m-%d 00:00:00' ),
							INTERVAL 0 SECOND 
						),
						INTERVAL 0 SECOND 
					) 
				) 
			) / ( 60 * 60 * 24 ) 
		) 
	) AS `avg_Calculation_505036481761304585_ok`,
	`company_sales_record`.`customer_name` AS `customer_name` 
FROM
	`company_sales_record`
	INNER JOIN (
	SELECT
		`company_sales_record`.`customer_name` AS `customer_name`,
		MIN( `company_sales_record`.`report_date` ) AS `__measure__0` 
	FROM
		`company_sales_record` 
	GROUP BY
		1 
	) `t0` ON ( `company_sales_record`.`customer_name` <=> `t0`.`customer_name` ) 
GROUP BY
	2

LOD相互嵌套實例

現在要求這樣一個問題,每種商品類型的銷售額與平均商品類型銷售額的差值。

首先我們要求平均商品類型銷售額,它計算的對象是各商品類型的總額的平均值,數學公式是 (類型1總額+類型2總額+...類型n總額)/商品類型數。我們可以創建一個average sales total per product type計算字段表示它。

{ EXCLUDE [product_type] : AVG({FIXED [product_type]:sum([price])})}

然后在行上使用臨時計算字段作為度量

SUM([price])-SUM([average sales total per product type])

列上拖入product_type維度

生成的SQL如下:

SELECT
	`t0`.`TEMP(Calculation_715016814539907077)(133835821)(0)` AS `TEMP(Calculation_715016814539907077)(133835821)(0)`,
	`t2`.`__measure__0` AS `TEMP(Calculation_715016814539907077)(919840309)(0)`,
	`t0`.`product_type` AS `product_type` 
FROM
	(
	SELECT
		`company_sales_record`.`product_type` AS `product_type`,
		SUM( `company_sales_record`.`price` ) AS `TEMP(Calculation_715016814539907077)(133835821)(0)` 
	FROM
		`company_sales_record` 
	GROUP BY
		1 
	) `t0`
	CROSS JOIN (
	SELECT
		AVG( `t1`.`__measure__1` ) AS `__measure__0` 
	FROM
		(
		SELECT
			SUM( `company_sales_record`.`price` ) AS `__measure__1` 
		FROM
			`company_sales_record` 
		GROUP BY
			`company_sales_record`.`product_type` 
		) `t1` 
	HAVING
		( COUNT( 1 ) > 0 ) 
	) `t2`

表計算示例

求銷售額的年同比

求銷售額的月環比

求銷售額的歷年累計


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM