Link Search Menu Expand Document Documentation Menu

聚合函数

聚合函数对 GROUP BY 子句定义的子集进行操作。如果没有 GROUP BY 子句,聚合函数将对结果集的所有元素进行操作。您可以在 GROUP BYSELECTHAVING 子句中使用聚合函数。

OpenSearch 支持以下聚合函数。

功能 描述
AVG 返回结果的平均值。
COUNT 返回结果的数量。
SUM 返回结果的总和。
MIN 返回结果的最小值。
MAX 返回结果的最大值。
VAR_POPVARIANCE 在丢弃空值后返回结果的总体方差。当只有一行结果时返回 0。
VAR_SAMP 在丢弃空值后返回结果的样本方差。当只有一行结果时返回 null。
STDSTDDEV 返回结果的样本标准差。当只有一行结果时返回 0。
STDDEV_POP 返回结果的总体标准差。当只有一行结果时返回 0。
STDDEV_SAMP 返回结果的样本标准差。当只有一行结果时返回 null。

以下示例引用了一个 employees 表。您可以通过使用批量索引操作将以下文档索引到 OpenSearch 中来尝试这些示例

PUT employees/_bulk?refresh
{"index":{"_id":"1"}}
{"employee_id": 1, "department":1, "firstname":"Amber", "lastname":"Duke", "sales":1356, "sale_date":"2020-01-23"}
{"index":{"_id":"2"}}
{"employee_id": 1, "department":1, "firstname":"Amber", "lastname":"Duke", "sales":39224, "sale_date":"2021-01-06"}
{"index":{"_id":"6"}}
{"employee_id":6, "department":1, "firstname":"Hattie", "lastname":"Bond", "sales":5686, "sale_date":"2021-06-07"}
{"index":{"_id":"7"}}
{"employee_id":6, "department":1, "firstname":"Hattie", "lastname":"Bond", "sales":12432, "sale_date":"2022-05-18"}
{"index":{"_id":"13"}}
{"employee_id":13,"department":2, "firstname":"Nanette", "lastname":"Bates", "sales":32838, "sale_date":"2022-04-11"}
{"index":{"_id":"18"}}
{"employee_id":18,"department":2, "firstname":"Dale", "lastname":"Adams", "sales":4180, "sale_date":"2022-11-05"}

GROUP BY

GROUP BY 子句定义了结果集的子集。聚合函数对这些子集进行操作,并为每个子集返回一行结果。

您可以在 GROUP BY 子句中使用标识符、序号或表达式。

在 GROUP BY 中使用标识符

您可以在 GROUP BY 子句中指定要聚合的字段名(列名)。例如,以下查询返回每个部门的部门编号和总销售额

SELECT department, sum(sales) 
FROM employees 
GROUP BY department;
department sum(sales)
1 58700
2 37018

在 GROUP BY 中使用序号

您可以在 GROUP BY 子句中指定要聚合的列号。列号由 SELECT 子句中的列位置决定。例如,以下查询与上面的查询等效。它返回每个部门的部门编号和总销售额。它按结果集的第一列(即 department)对结果进行分组

SELECT department, sum(sales) 
FROM employees 
GROUP BY 1;
department sum(sales)
1 58700
2 37018

在 GROUP BY 中使用表达式

您可以在 GROUP BY 子句中使用表达式。例如,以下查询返回每年的平均销售额

SELECT year(sale_date), avg(sales) 
FROM employees 
GROUP BY year(sale_date);
year(start_date) avg(sales)
2020 1356.0
2021 22455.0
2022 16484.0

SELECT

您可以在 SELECT 子句中直接使用聚合表达式,或作为更大表达式的一部分使用。此外,您可以使用表达式作为聚合函数的参数。

直接在 SELECT 中使用聚合表达式

以下查询返回每个部门的平均销售额

SELECT department, avg(sales) 
FROM employees 
GROUP BY department;
department avg(sales)
1 14675.0
2 18509.0

在 SELECT 中将聚合表达式用作更大表达式的一部分

以下查询计算每个部门员工的平均佣金,为平均销售额的 5%

SELECT department, avg(sales) * 0.05 as avg_commission 
FROM employees 
GROUP BY department;
department avg_commission
1 733.75
2 925.45

使用表达式作为聚合函数的参数

以下查询计算每个部门的平均佣金金额。它首先计算每个 sales 值的佣金金额,即 sales 的 5%。然后确定所有佣金值的平均值

SELECT department, avg(sales * 0.05) as avg_commission 
FROM employees 
GROUP BY department;
department avg_commission
1 733.75
2 925.45

COUNT

COUNT 函数接受参数,例如 *,或字面量,例如 1。下表描述了 COUNT 函数的各种形式如何操作。

函数类型 描述
COUNT(field) 计算给定字段(或表达式)的值不为 null 的行数。
COUNT(*) 计算表中的总行数。
COUNT(1)(同 COUNT(*) 计算任何非 null 的字面量。

例如,以下查询返回每年的销售额计数

SELECT year(sale_date), count(sales) 
FROM employees 
GROUP BY year(sale_date);
year(sale_date) count(sales)
2020 1
2021 2
2022 3

HAVING

WHEREHAVING 都用于过滤结果。WHERE 过滤器在 GROUP BY 阶段之前应用,因此您不能在 WHERE 子句中使用聚合函数。但是,您可以使用 WHERE 子句来限制应用聚合的行。

HAVING 过滤器在 GROUP BY 阶段之后应用,因此您可以使用 HAVING 子句来限制包含在结果中的组。

带 GROUP BY 的 HAVING

您可以在 HAVING 条件中使用聚合表达式或其在 SELECT 子句中定义的别名。

以下查询在 HAVING 子句中使用聚合表达式。它返回每个销售额超过一次的员工的销售额数量

SELECT employee_id, count(sales)
FROM employees
GROUP BY employee_id
HAVING count(sales) > 1;
employee_id count(sales)
1 2
6 2

HAVING 子句中的聚合不必与 SELECT 列表中的聚合相同。以下查询在 HAVING 子句中使用 count 函数,但在 SELECT 子句中使用 sum 函数。它返回每个销售额超过一次的员工的总销售额

SELECT employee_id, sum(sales)
FROM employees
GROUP BY employee_id
HAVING count(sales) > 1;
employee_id sum (sales)
1 40580
6 18120

作为 SQL 标准的扩展,您不限于在 GROUP BY 子句中仅使用标识符。以下查询在 GROUP BY 子句中使用别名,并且与上一个查询等效

SELECT employee_id as id, sum(sales)
FROM employees
GROUP BY id
HAVING count(sales) > 1;
id sum (sales)
1 40580
6 18120

您也可以在 HAVING 子句中使用聚合表达式的别名。以下查询返回销售额超过 40,000 美元的每个部门的总销售额

SELECT department, sum(sales) as total
FROM employees
GROUP BY department
HAVING total > 40000;
department total
1 58700

如果标识符不明确(例如,同时作为 SELECT 别名和索引字段存在),则优先选择别名。在以下查询中,标识符被替换为在 SELECT 子句中指定别名的表达式

SELECT department, sum(sales) as sales
FROM employees
GROUP BY department
HAVING sales > 40000;
department sales
1 58700

不带 GROUP BY 的 HAVING

您可以在没有 GROUP BY 子句的情况下使用 HAVING 子句。在这种情况下,整个数据集被视为一个组。以下查询将在 department 列中存在多个值时返回 True

SELECT 'True' as more_than_one_department FROM employees HAVING min(department) < max(department);
more_than_one_department
True

如果员工表中的所有员工都属于同一部门,则结果将包含零行

more_than_one_department