# 内部和外部集合表达式

集合表达式可以在聚合函数内外使用，并用花括号括起来。

在聚合函数中使用集合表达式时，它可能如下所示：

示例： 内部集合表达式

```
Sum( {$<Year={2021}>} Sales )
```

如果表达式具有多个聚合，并且希望避免在每个聚合函数中写入相同的集合表达式，请在聚合函数外使用集合表达式。

如果使用外部集合表达式，则必须将其放置在范围的开头。

示例： 外部集合表达式

```
{<Year={2021}>} Sum(Sales) / Count(distinct Customer)
```

如果在聚合函数之外使用集合表达式，也可以将其应用于现有的主度量值。

示例： 应用于主度量值的外部集表达式

```
{<Year={2021}>} [Master Measure]
```

在聚合函数外部使用的集合表达式会影响整个表达式，除非它用括号括起来，否则括号定义范围。在下面的词法范围示例中，集合表达式仅应用于括号内的聚合。

示例： 词法定界

```
( {<Year={2021}>} Sum(Amount) / Count(distinct Customer) ) – Avg(CustomerSales)
```

## 规则

#### 词法定界

除非用括号括起来，否则集合表达式会影响整个表达式。如果是，括号定义词法范围。

#### 位置

集合表达式必须放在词法范围的开头。

#### 上下文

上下文是与表达式相关的选择。传统上，上下文始终是当前选择的默认状态。但如果对象设置为备用状态，则上下文是当前选择的备用状态。

还可以以外部集表达式的形式定义上下文。

#### 继承

内部集合表达式优先于外部集合表达式。如果内部集合表达式包含集合标识符，则它会覆盖外部集合表达式中定义的上下文。否则，将计算内部和外部集合表达式。

示例 1: 带有集合标识符的内部集合表达式

{&lt;Year={2023}&gt;} Sum(Sales) / Count({1} distinct OrderNumber)

在上述表达式中，内部集合表达式 Count({1} distinct OrderNumber) 由集合标识符 {1} 组成。计算此内部集合表达式时，不应用外部集合表达式 {&lt;Year={2023}&gt;} 中定义的范围。

示例 2: 没有集合标识符的内部集合表达式

{&lt;Year={2023}&gt;} Sum ({&lt;Status={'Confirmed'}&gt;} Sales\_Stream1) + Sum ({&lt;UpdatedStatus={'Confirmed'}&gt;} Sales\_Stream2)

在上述表达式中，内部集合表达式 Sum ({&lt;Status={'Confirmed'}&gt;} Sales\_Stream1) 和 Sum ({&lt;UpdatedStatus={'Confirmed'}&gt;} Sales\_Stream2) 不包含集合标识符。因此，在评估结果时，外部集合表达式 {&lt;Year={2023}&gt;} 和两个内部集合表达式都被应用。

#### 元素集分配

元素集指定决定了如何合并两个选择。如果使用法线等号，则内部集合表达式中的选择具有优先权。否则，将使用隐式集合运算符。

* {&lt;Field={value}&gt;} - 此内部选择将替换 “Field” 中的任何外部选择。

* {&lt;Field+={value}&gt;} - 使用并集运算符，此内部选择与 “Field” 中的外部选择合并。

* {&lt;Field\*={value}&gt;} - 使用交叉运算符，此内部选择与 “Field” 中的外部选择合并。

#### 多步骤继承

继承可以分多个步骤进行。示例：

* 当前选择项 → Sum(Amount)

  聚合函数将使用上下文，这是当前选择。

* 当前选择项 → {&lt;Set1&gt;} Sum(Amount)

  Set1 将从当前选择继承，结果将是聚合函数的上下文。

* 当前选择项 → {&lt;Set1&gt;} ({&lt;Set2&gt;} Sum(Amount))

  Set2 将从 Set1 继承，其将从当前选择继承，结果将是聚合函数的上下文。

#### 内部和外部集合表达式的链继承

在复杂链中使用多个集合表达式时，尤其是外部集合表达式后面有其他外部集合表达式和/或内部集合表达式时，在继承方面还有更多的考虑因素。有关详细信息，请参阅[多个外部集合和内部集合表达式链](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/ChartFunctions/SetAnalysis/set-expressions-inner-and-outer.htm#Chains)。

#### Aggr() 函数

Aggr() 函数创建一个具有两个独立聚合的嵌套聚合。在下面的示例中，为 Dim 的每个值计算 Count()，并使用 Sum() 函数聚合得到的数组。

示例：

```
Sum(Aggr(Count(X),Dim))
```

Count() 是内部聚合，Sum() 是外部聚合。

* 内部聚合未从外部聚合继承任何上下文。

* 内部聚合从 Aggr() 函数继承上下文，该函数可能包含集合表达式。

* Aggr() 函数和外部聚合函数都从外部集表达式继承上下文。

## 多个外部集合和内部集合表达式链

请注意，外部集合表达式可能不止一个。在该例子中，我们有两个外部集合表达式和一个内部集合表达式：

{&lt;Year={2021}&gt;} {&lt;Region={"Europe"}&gt;} Sum( {$&lt;Product={"XI345"}&gt;} Sales )

集合表达式将从左到右依次地应用。这意味着，如果两个集合表达式使用了互相冲突的集合，则最右边表达式优先。

虽然以这种方式串联起来的外部集合表达式的数量没有限制，但内部集合表达式的数量仅限于一个。多个内部集合表达式相邻不会产生任何错误，但在求值时只会使用最右边的表达式。

### 设置表达式继承

当一个聚合表达式包含多个集合表达式作为链的一部分时，集合表达式将从左至右逐个求值。每个集合表达式的结果是一组集合，每个维度可能具有一个集合。这些集合会传递给下一个集合表达式，表达式可以在传递给下一个集合表达式之前执行进一步修改。

只要每个集合表达式在不同维度上运行，它们之间就不会发生冲突，所有集合都将保留到链的末端（并在聚合之时应用）。这条规则有一个例外，有时适用于集合表达式中维度产生了空集合的情况。更多信息请参阅以下内容：

* [空选择集合](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/ChartFunctions/SetAnalysis/set-expressions-inner-and-outer.htm#Empty)

* [隐式选择集合清除](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/ChartFunctions/SetAnalysis/set-expressions-inner-and-outer.htm#Implicit)

### 空选择集合

当对集合表达式中维度进行求值时，集合有可能不包含任何数据。这就是所谓的空集合。空集合在很多情况下都会出现，例如

* 表达式定义错误。例如，当尝试使用集合表达式 {&lt;OrderYear={‘2025’}&gt;} 查找值 2025 时，表达式被写成 {&lt;OrderYear={‘0025’}&gt;}。

* 在分析过程中，在与表达式中引用的维度不同的维度中进行选择，而这种选择导致所设置表达式维度没有可用数据。例如，用户选择 Region='Europe' ，并设置表达式筛选器 {&lt;ProductCategory={‘Shirts’}&gt;} Sum (Sales) 。如果在欧洲没有销售衬衫，则集合表达式包含一个空集合。

* 表达式中明确定义了空集合。这并不常见，也不实用，但在技术上可行。例如： {&lt;Year={}&gt;}

### 隐式选择集合清除

如果应用集合表达式后的结果是任何一个维度的空集合（请参阅[空选择集合](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/ChartFunctions/SetAnalysis/set-expressions-inner-and-outer.htm#Empty)），并且在此之后还有一个集合表达式正在应用，那么在应用下一个集合表达式之前，该维度的选择集合将被清除（恢复至整个集合）。清除选择集合意味着包含所有值。但是请注意，只有在生成空集合的集合表达式之后应用了一个或多个额外的外部集合表达式时，才会发生这种清除。

下面举例说明何时会发生清除选择集合的情况：

```
{<Year={}>} {<Region={"Europe"}>} Sum( Sales )
```

Year={} 将为维度 Year 创建空集合。这意味着，当把 Year 的选择集合传递给下一个包含 Region={Europe} 的集合表达式时，该集合将被清除。请注意，选择清除只适用于单一维度。其他维度的集合 - 包括同一集合表达式中的集合 - 仍将不加更改地传递。

以下是清除的选择集合的另一个示例：

```
{<Year={}, Product={"XI345"}>} {<Region={"Europe"}>} Sum(Sales)
```

在上述示例中，会出现以下情况：

* 应用选择集合 Product={"XI345"} 和 Region={"Europe"} 。

* Year={} 不适用。这是因为在应用最后一个集合表达式 {&lt;Region={"Europe"}&gt;} 时，该集合会被清除。

将集合表达式组件移至最后一个外部集合表达式将防止发生隐式清除。以下为示例：

```
{<Product={"XI345"}>} {<Year={}, Region={"Europe"}>} Sum(Sales)
```

在这里，我们将 Year 表达式移动到链中的最后一个集合表达式中。这将防止发生隐式清除，而 Year 维度的空集合将实际用于 Sum 聚合。

在任何情况下，当清除选择集合时，都可能发生不希望发生的行为。为了改善分析体验，并更容易编写集合表达式链，请使用空集合保留标志。有关更多信息，请参阅[空集合保留标志（外部集合表达式）](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/ChartFunctions/SetAnalysis/set-expressions-inner-and-outer.htm#Flag)。

## 空集合保留标志（外部集合表达式）

使用 & 符号（空集合保留标志）可简化外部集合表达式的求值模型。例如：

```
{& <Year={}, Product={XI345}>} {<Region={Europe}>} Sum( Sales )
```

在本例中，Year={} 为 Year 定义了一个空的选择集合。如果没有 & 符号，{&lt;Region={Europe}&gt;} 表达式将导致 Year 空选择集合被清除，从而导致所有数据都被用于汇总计算。& 符号迫使聚合过程遵循 Year 空选择集合，从而使输出结果更易于理解。

有关空集合保留标志的全部详情，请参阅[空集合保留标志](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/ChartFunctions/SetAnalysis/empty-set-preserve-flag.htm) 。

## 了解详情

* [美元符号扩展](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/Scripting/dollar-sign-expansions.htm)

* [创建变量](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/Variables/create-variable-using-dialog.htm)

* [变量对话框](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/Sheets/variables-dialog.htm)

* [外集表达式和货币符号扩展](https://help.qlik.com/zh-CN/cloud-services/Subsystems/Hub/Content/Sense_Hub/ChartFunctions/SetAnalysis/outer-set-expression-dollar-sign-expansion.htm)