---
schema_version: "1"
id: 3c7f23c3ae1b5410770ef31b3664e3acb5a09fd92fc20eab200dc9dbfd2cf698
title: Tableau 中创建计算的最佳做法
collection: tableau
version: current
locale: zh-cn
portal_url: https://docs.salesforce.com/tableau/current/zh-cn/public/desktop/calculations_calculatedfields_bestpractices.md
canonical_url: https://help.tableau.com/current/public/desktop/zh-cn/calculations_calculatedfields_bestpractices.htm
source_site: help.tableau.com
content_type: documentation
content_hash: 0bff9fecd1d8464cff84fcb909f287424702ccffa9df04618942d676e09c8358
description: Tips and guidelines for creating efficient calculations in Tableau to optimize workbook performance.
---
[跳转到主要内容](#main-content)

# 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

创建组，而不是计算字段。有关详细信息，请参见[对数据进行分组](https://help.tableau.com/current/public/desktop/zh-cn/sortgroup_groups_creating.htm)。

## 提示 2：将多个字符串计算转换为单一 REGEXP 表达式

**注意**：REGEXP 计算仅在使用 Tableau 数据提取或连接到文本文件、Hadoop Hive、Google BigQuery、PostgreSQL、Tableau 数据提取、Microsoft Excel、Salesforce、Vertica、Pivotal Greenplum、Teradata（版本 14.1 及更高版本）和 Oracle 数据源时可用。有关详细信息，请参见[其他函数（正则表达式、Hadoop Hive、Google Big Query）](https://help.tableau.com/current/public/desktop/zh-cn/functions_functions_additional.htm)。

  

### 示例 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（成为正则表达式精英并照管不完美的数据）](https://www.tableau.com/zh-cn/about/blog/2015/6/become-regular-regular-expressions-39802)博文。

### 示例 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`

有关详细信息，请参见[对数据进行分组](https://help.tableau.com/current/public/desktop/zh-cn/sortgroup_groups_creating.htm)和[创建集](https://help.tableau.com/current/public/desktop/zh-cn/sortgroup_sets_create.htm)。

## 提示 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`

之所以不推荐这样做，有以下几个原因：

- **集并不始终是排他的。**某些成员可能会出现在多个集中。例如，“俄罗斯”既可能放在“欧洲”集中，也可能放在“亚洲”集中。
- **集并不会始终转换为组。**如果集是通过排除、条件或限制定义的，则可能很难甚至无法创建等效的组。

### 解决方案

使用“组”功能对数据进行分组。有关详细信息，请参见[对数据进行分组](https://help.tableau.com/current/public/desktop/zh-cn/sortgroup_groups_creating.htm)。

## 另请参见

[Tableau 中的计算类型](https://help.tableau.com/current/public/desktop/zh-cn/calculations_calculatedfields_understand_types.htm)

[Tableau 中的函数](https://help.tableau.com/current/public/desktop/zh-cn/functions.htm)