本节介绍对值集进行操作的聚合函数。它们通常与 GROUP BY
子句一起使用,将值分组到子集中。
表 14.29 聚合函数
名称 | 描述 |
---|---|
AVG() |
返回参数的平均值 |
BIT_AND() |
返回按位与 |
BIT_OR() |
返回按位或 |
BIT_XOR() |
返回按位异或 |
COUNT() |
返回返回的行数的计数 |
COUNT(DISTINCT) |
返回不同值的数量的计数 |
GROUP_CONCAT() |
返回连接的字符串 |
JSON_ARRAYAGG() |
将结果集作为单个 JSON 数组返回 |
JSON_OBJECTAGG() |
将结果集作为单个 JSON 对象返回 |
MAX() |
返回最大值 |
MIN() |
返回最小值 |
STD() |
返回总体标准偏差 |
STDDEV() |
返回总体标准偏差 |
STDDEV_POP() |
返回总体标准偏差 |
STDDEV_SAMP() |
返回样本标准偏差 |
SUM() |
返回总和 |
VAR_POP() |
返回总体标准方差 |
VAR_SAMP() |
返回样本方差 |
VARIANCE() |
返回总体标准方差 |
除非另有说明,否则聚合函数会忽略 NULL
值。
如果在不包含 GROUP BY
子句的语句中使用聚合函数,则等效于对所有行进行分组。有关更多信息,请参见 第 14.19.3 节“MySQL 对 GROUP BY 的处理”。
大多数聚合函数可以用作窗口函数。可以通过 [
在其语法描述中表示可以用作窗口函数的函数,表示可选的 over_clause
]OVER
子句。 over_clause
在 第 14.20.2 节“窗口函数概念和语法” 中进行了描述,其中还包括有关窗口函数用法的其他信息。
对于数值参数,方差和标准偏差函数返回 DOUBLE
值。 SUM()
和 AVG()
函数对于精确值参数(整数或 DECIMAL
)返回 DECIMAL
值,对于近似值参数(FLOAT
或 DOUBLE
)返回 DOUBLE
值。
SUM()
和 AVG()
聚合函数不适用于时间值。(它们会将值转换为数字,并丢失第一个非数字字符之后的所有内容。)要解决此问题,请转换为数字单位,执行聚合操作,然后转换回时间值。示例
SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(time_col))) FROM tbl_name;
SELECT FROM_DAYS(SUM(TO_DAYS(date_col))) FROM tbl_name;
如果需要,诸如 SUM()
或 AVG()
之类的函数会将参数转换为数字。对于 SET
或 ENUM
值,强制转换操作会导致使用基础数字值。
BIT_AND()
、BIT_OR()
和 BIT_XOR()
聚合函数执行位运算。
MySQL 位函数和运算符允许使用二进制字符串类型参数(BINARY
、VARBINARY
和 BLOB
类型)并返回类似类型的返回值,这使它们能够接受大于 64 位的参数并生成返回值。有关位运算的参数求值和结果类型的讨论,请参见 第 14.12 节“位函数和运算符” 中的介绍性讨论。
AVG([DISTINCT]
expr
) [over_clause
]返回
的平均值。expr
DISTINCT
选项可用于返回expr
的不同值的平均值。如果没有匹配的行,则
AVG()
返回NULL
。如果expr
为NULL
,该函数也会返回NULL
。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述;它不能与DISTINCT
一起使用。mysql> SELECT student_name, AVG(test_score) FROM student GROUP BY student_name;
返回
expr
中所有位的按位AND
。结果类型取决于函数参数值是作为二进制字符串还是数字求值的
当参数值为二进制字符串类型,并且参数不是十六进制字面量、位字面量或
NULL
字面量时,将进行二进制字符串计算。否则,将进行数值计算,并根据需要将参数值转换为无符号 64 位整数。二进制字符串计算会生成一个与参数值长度相同的二进制字符串。如果参数值的长度不相等,则会发生
ER_INVALID_BITWISE_OPERANDS_SIZE
错误。如果参数大小超过 511 字节,则会发生ER_INVALID_BITWISE_AGGREGATE_OPERANDS_SIZE
错误。数值计算会生成一个无符号的 64 位整数。
如果没有匹配的行,
BIT_AND()
将返回一个中性值(所有位都设置为 1),其长度与参数值相同。NULL
值不会影响结果,除非所有值都是NULL
。在这种情况下,结果是一个与参数值长度相同的中性值。有关参数计算和结果类型的更多信息,请参见 第 14.12 节“位函数和运算符” 中的介绍性讨论。
如果从 mysql 客户端中调用
BIT_AND()
,则二进制字符串结果将使用十六进制表示法显示,具体取决于--binary-as-hex
的值。有关该选项的更多信息,请参见 第 6.5.1 节“mysql — MySQL 命令行客户端”。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述。返回
expr
中所有位的按位OR
。结果类型取决于函数参数值是作为二进制字符串还是数字求值的
当参数值为二进制字符串类型,并且参数不是十六进制字面量、位字面量或
NULL
字面量时,将进行二进制字符串计算。否则,将进行数值计算,并根据需要将参数值转换为无符号 64 位整数。二进制字符串计算会生成一个与参数值长度相同的二进制字符串。如果参数值的长度不相等,则会发生
ER_INVALID_BITWISE_OPERANDS_SIZE
错误。如果参数大小超过 511 字节,则会发生ER_INVALID_BITWISE_AGGREGATE_OPERANDS_SIZE
错误。数值计算会生成一个无符号的 64 位整数。
如果没有匹配的行,
BIT_OR()
将返回一个中性值(所有位都设置为 0),其长度与参数值相同。NULL
值不会影响结果,除非所有值都是NULL
。在这种情况下,结果是一个与参数值长度相同的中性值。有关参数计算和结果类型的更多信息,请参见 第 14.12 节“位函数和运算符” 中的介绍性讨论。
如果从 mysql 客户端中调用
BIT_OR()
,则二进制字符串结果将使用十六进制表示法显示,具体取决于--binary-as-hex
的值。有关该选项的更多信息,请参见 第 6.5.1 节“mysql — MySQL 命令行客户端”。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述。返回
expr
中所有位的按位XOR
。结果类型取决于函数参数值是作为二进制字符串还是数字求值的
当参数值为二进制字符串类型,并且参数不是十六进制字面量、位字面量或
NULL
字面量时,将进行二进制字符串计算。否则,将进行数值计算,并根据需要将参数值转换为无符号 64 位整数。二进制字符串计算会生成一个与参数值长度相同的二进制字符串。如果参数值的长度不相等,则会发生
ER_INVALID_BITWISE_OPERANDS_SIZE
错误。如果参数大小超过 511 字节,则会发生ER_INVALID_BITWISE_AGGREGATE_OPERANDS_SIZE
错误。数值计算会生成一个无符号的 64 位整数。
如果没有匹配的行,
BIT_XOR()
将返回一个中性值(所有位都设置为 0),其长度与参数值相同。NULL
值不会影响结果,除非所有值都是NULL
。在这种情况下,结果是一个与参数值长度相同的中性值。有关参数计算和结果类型的更多信息,请参见 第 14.12 节“位函数和运算符” 中的介绍性讨论。
如果从 mysql 客户端中调用
BIT_XOR()
,则二进制字符串结果将使用十六进制表示法显示,具体取决于--binary-as-hex
的值。有关该选项的更多信息,请参见 第 6.5.1 节“mysql — MySQL 命令行客户端”。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述。返回由
SELECT
语句检索的行中expr
的非NULL
值的数量。结果是一个BIGINT
值。如果没有匹配的行,
COUNT()
将返回0
。COUNT(NULL)
返回 0。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述。mysql> SELECT student.student_name,COUNT(*) FROM student,course WHERE student.student_id=course.student_id GROUP BY student_name;
COUNT(*)
有所不同,因为它返回检索到的行数,无论它们是否包含NULL
值。对于事务性存储引擎(如
InnoDB
),存储确切的行数是有问题的。多个事务可能同时发生,每个事务都可能影响计数。InnoDB
不会保留表中行的内部计数,因为并发事务可能同时““看到” 不同数量的行。因此,SELECT COUNT(*)
语句仅计算当前事务可见的行。如果不存在
WHERE
或GROUP BY
等额外子句,则针对单线程工作负载优化了InnoDB
表的SELECT COUNT(*) FROM
查询性能。tbl_name
InnoDB
通过遍历最小的可用二级索引来处理SELECT COUNT(*)
语句,除非索引或优化器提示指示优化器使用不同的索引。如果不存在二级索引,InnoDB
通过扫描聚簇索引来处理SELECT COUNT(*)
语句。如果索引记录不完全在缓冲池中,则处理
SELECT COUNT(*)
语句需要一些时间。为了更快地计数,请创建一个计数器表,并让您的应用程序根据其执行的插入和删除操作对其进行更新。但是,在数千个并发事务启动对同一个计数器表的更新的情况下,此方法可能无法很好地扩展。如果近似的行数就足够了,请使用SHOW TABLE STATUS
。InnoDB
以相同的方式处理SELECT COUNT(*)
和SELECT COUNT(1)
操作。性能没有区别。对于
MyISAM
表,如果SELECT
从一个表中检索数据,没有检索其他列,并且没有WHERE
子句,则对COUNT(*)
进行了优化,可以非常快地返回结果。例如:mysql> SELECT COUNT(*) FROM student;
此优化仅适用于
MyISAM
表,因为此存储引擎存储了确切的行数,并且可以非常快速地访问。只有当第一列定义为NOT NULL
时,COUNT(1)
才适用相同的优化。COUNT(DISTINCT
expr
,[expr
...])返回具有不同非
NULL
expr
值的行数。如果没有匹配的行,
COUNT(DISTINCT)
将返回0
。mysql> SELECT COUNT(DISTINCT results) FROM student;
在 MySQL 中,您可以通过提供表达式列表来获取不包含
NULL
的不同表达式组合的数量。在标准 SQL 中,您必须在COUNT(DISTINCT ...)
中对所有表达式进行串联。此函数返回一个字符串结果,其中包含来自组的串联非
NULL
值。如果没有非NULL
值,则返回NULL
。完整的语法如下:GROUP_CONCAT([DISTINCT] expr [,expr ...] [ORDER BY {unsigned_integer | col_name | expr} [ASC | DESC] [,col_name ...]] [SEPARATOR str_val])
mysql> SELECT student_name, GROUP_CONCAT(test_score) FROM student GROUP BY student_name;
或
mysql> SELECT student_name, GROUP_CONCAT(DISTINCT test_score ORDER BY test_score DESC SEPARATOR ' ') FROM student GROUP BY student_name;
在 MySQL 中,您可以获取表达式组合的串联值。要消除重复值,请使用
DISTINCT
子句。要对结果中的值进行排序,请使用ORDER BY
子句。要按降序排序,请在ORDER BY
子句中要排序的列名称中添加DESC
(降序)关键字。默认值为升序;可以使用ASC
关键字显式指定。组中值之间的默认分隔符是逗号 (,
)。要显式指定分隔符,请使用SEPARATOR
,后跟应插入组值之间的字符串字面量值。要完全消除分隔符,请指定SEPARATOR ''
。结果将被截断为
group_concat_max_len
系统变量给定的最大长度,该变量的默认值为 1024。该值可以设置得更高,但返回值的有效最大长度受max_allowed_packet
值的限制。在运行时更改group_concat_max_len
值的语法如下,其中val
是一个无符号整数:SET [GLOBAL | SESSION] group_concat_max_len = val;
返回值是非二进制字符串还是二进制字符串,取决于参数是非二进制字符串还是二进制字符串。结果类型为
TEXT
或BLOB
,除非group_concat_max_len
小于或等于 512,在这种情况下,结果类型为VARCHAR
或VARBINARY
。如果从 mysql 客户端中调用
GROUP_CONCAT()
,则二进制字符串结果将使用十六进制表示法显示,具体取决于--binary-as-hex
的值。有关该选项的更多信息,请参见 第 6.5.1 节“mysql — MySQL 命令行客户端”。另请参见
CONCAT()
和CONCAT_WS()
:第 14.8 节“字符串函数和运算符”。JSON_ARRAYAGG(
col_or_expr
) [over_clause
]将结果集聚合为单个
JSON
数组,其元素由行组成。此数组中元素的顺序未定义。该函数作用于一个列或一个计算结果为单个值的表达式。如果结果不包含任何行或发生错误,则返回NULL
。如果col_or_expr
为NULL
,则该函数返回一个 JSON[null]
元素数组。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述。mysql> SELECT o_id, attribute, value FROM t3; +------+-----------+-------+ | o_id | attribute | value | +------+-----------+-------+ | 2 | color | red | | 2 | fabric | silk | | 3 | color | green | | 3 | shape | square| +------+-----------+-------+ 4 rows in set (0.00 sec) mysql> SELECT o_id, JSON_ARRAYAGG(attribute) AS attributes -> FROM t3 GROUP BY o_id; +------+---------------------+ | o_id | attributes | +------+---------------------+ | 2 | ["color", "fabric"] | | 3 | ["color", "shape"] | +------+---------------------+ 2 rows in set (0.00 sec)
JSON_OBJECTAGG(
key
,value
) [over_clause
]将两个列名或表达式作为参数,第一个用作键,第二个用作值,并返回一个包含键值对的 JSON 对象。如果结果不包含任何行或发生错误,则返回
NULL
。如果任何键名都是NULL
或参数数量不等于 2,则会发生错误。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述。mysql> SELECT o_id, attribute, value FROM t3; +------+-----------+-------+ | o_id | attribute | value | +------+-----------+-------+ | 2 | color | red | | 2 | fabric | silk | | 3 | color | green | | 3 | shape | square| +------+-----------+-------+ 4 rows in set (0.00 sec) mysql> SELECT o_id, JSON_OBJECTAGG(attribute, value) -> FROM t3 GROUP BY o_id; +------+---------------------------------------+ | o_id | JSON_OBJECTAGG(attribute, value) | +------+---------------------------------------+ | 2 | {"color": "red", "fabric": "silk"} | | 3 | {"color": "green", "shape": "square"} | +------+---------------------------------------+ 2 rows in set (0.00 sec)
重复键处理。 当此函数的结果被规范化时,具有重复键的值将被丢弃。为了与不允许重复键的 MySQL
JSON
数据类型规范保持一致,在返回的对象中,只有遇到的最后一个值会与该键一起使用(“最后一个重复键优先”)。这意味着,对来自SELECT
的列使用此函数的结果可能取决于返回行的顺序,而该顺序是不保证的。当用作窗口函数时,如果一个框架内存在重复的键,则结果中只存在该键的最后一个值。如果
ORDER BY
规范保证了值的特定顺序,则框架中最后一行键的值是确定的。如果不是,则键的结果值是不确定的。考虑以下内容
mysql> CREATE TABLE t(c VARCHAR(10), i INT); Query OK, 0 rows affected (0.33 sec) mysql> INSERT INTO t VALUES ('key', 3), ('key', 4), ('key', 5); Query OK, 3 rows affected (0.10 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> SELECT c, i FROM t; +------+------+ | c | i | +------+------+ | key | 3 | | key | 4 | | key | 5 | +------+------+ 3 rows in set (0.00 sec) mysql> SELECT JSON_OBJECTAGG(c, i) FROM t; +----------------------+ | JSON_OBJECTAGG(c, i) | +----------------------+ | {"key": 5} | +----------------------+ 1 row in set (0.00 sec) mysql> DELETE FROM t; Query OK, 3 rows affected (0.08 sec) mysql> INSERT INTO t VALUES ('key', 3), ('key', 5), ('key', 4); Query OK, 3 rows affected (0.06 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> SELECT c, i FROM t; +------+------+ | c | i | +------+------+ | key | 3 | | key | 5 | | key | 4 | +------+------+ 3 rows in set (0.00 sec) mysql> SELECT JSON_OBJECTAGG(c, i) FROM t; +----------------------+ | JSON_OBJECTAGG(c, i) | +----------------------+ | {"key": 4} | +----------------------+ 1 row in set (0.00 sec)
从最后一个查询中选择的键是不确定的。如果查询没有使用
GROUP BY
(它通常会施加自己的排序,而不管是什么顺序),并且您希望使用特定的键排序,则可以通过包含带有ORDER BY
规范的OVER
子句来调用JSON_OBJECTAGG()
作为窗口函数,以便对框架行施加特定的顺序。以下示例显示了在几种不同的框架规范中,使用和不使用ORDER BY
会发生什么。不使用
ORDER BY
时,框架是整个分区mysql> SELECT JSON_OBJECTAGG(c, i) OVER () AS json_object FROM t; +-------------+ | json_object | +-------------+ | {"key": 4} | | {"key": 4} | | {"key": 4} | +-------------+
使用
ORDER BY
时,其中框架是RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
的默认值(升序和降序都是如此)mysql> SELECT JSON_OBJECTAGG(c, i) OVER (ORDER BY i) AS json_object FROM t; +-------------+ | json_object | +-------------+ | {"key": 3} | | {"key": 4} | | {"key": 5} | +-------------+ mysql> SELECT JSON_OBJECTAGG(c, i) OVER (ORDER BY i DESC) AS json_object FROM t; +-------------+ | json_object | +-------------+ | {"key": 5} | | {"key": 4} | | {"key": 3} | +-------------+
使用
ORDER BY
和整个分区的显式框架mysql> SELECT JSON_OBJECTAGG(c, i) OVER (ORDER BY i ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS json_object FROM t; +-------------+ | json_object | +-------------+ | {"key": 5} | | {"key": 5} | | {"key": 5} | +-------------+
要返回特定的键值(例如最小值或最大值),请在相应的查询中包含
LIMIT
子句。例如mysql> SELECT JSON_OBJECTAGG(c, i) OVER (ORDER BY i) AS json_object FROM t LIMIT 1; +-------------+ | json_object | +-------------+ | {"key": 3} | +-------------+ mysql> SELECT JSON_OBJECTAGG(c, i) OVER (ORDER BY i DESC) AS json_object FROM t LIMIT 1; +-------------+ | json_object | +-------------+ | {"key": 5} | +-------------+
有关更多信息和示例,请参见 JSON 值的规范化、合并和自动包装。
MAX([DISTINCT]
expr
) [over_clause
]返回
expr
的最大值。MAX()
可以接受字符串参数;在这种情况下,它将返回最大字符串值。请参见 第 10.3.1 节“MySQL 如何使用索引”。可以使用DISTINCT
关键字查找expr
的不同值中的最大值,但这会产生与省略DISTINCT
相同的结果。如果没有匹配的行,或者
expr
为NULL
,则MAX()
返回NULL
。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述;它不能与DISTINCT
一起使用。mysql> SELECT student_name, MIN(test_score), MAX(test_score) FROM student GROUP BY student_name;
对于
MAX()
,MySQL 目前是通过ENUM
和SET
列的字符串值而不是字符串在集合中的相对位置来比较它们的。这与ORDER BY
比较它们的方式不同。MIN([DISTINCT]
expr
) [over_clause
]返回
expr
的最小值。MIN()
可以接受字符串参数;在这种情况下,它将返回最小字符串值。请参见 第 10.3.1 节“MySQL 如何使用索引”。可以使用DISTINCT
关键字查找expr
的不同值中的最小值,但这会产生与省略DISTINCT
相同的结果。如果没有匹配的行,或者
expr
为NULL
,则MIN()
返回NULL
。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述;它不能与DISTINCT
一起使用。mysql> SELECT student_name, MIN(test_score), MAX(test_score) FROM student GROUP BY student_name;
对于
MIN()
,MySQL 目前是通过ENUM
和SET
列的字符串值而不是字符串在集合中的相对位置来比较它们的。这与ORDER BY
比较它们的方式不同。返回
expr
的总体标准偏差。STD()
是标准 SQL 函数STDDEV_POP()
的同义词,作为 MySQL 扩展提供。如果没有匹配的行,或者
expr
为NULL
,则STD()
返回NULL
。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述。返回
expr
的总体标准偏差。STDDEV()
是标准 SQL 函数STDDEV_POP()
的同义词,为了与 Oracle 兼容而提供。如果没有匹配的行,或者
expr
为NULL
,则STDDEV()
返回NULL
。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述。STDDEV_POP(
expr
) [over_clause
]返回
expr
的总体标准偏差(VAR_POP()
的平方根)。您也可以使用STD()
或STDDEV()
,它们是等效的,但不是标准 SQL。如果没有匹配的行,或者
expr
为NULL
,则STDDEV_POP()
返回NULL
。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述。STDDEV_SAMP(
expr
) [over_clause
]返回
expr
的样本标准偏差(VAR_SAMP()
的平方根)。如果没有匹配的行,或者
expr
为NULL
,则STDDEV_SAMP()
返回NULL
。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述。SUM([DISTINCT]
expr
) [over_clause
]返回
expr
的总和。如果返回集没有行,则SUM()
返回NULL
。可以使用DISTINCT
关键字仅对expr
的不同值求和。如果没有匹配的行,或者
expr
为NULL
,则SUM()
返回NULL
。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述;它不能与DISTINCT
一起使用。返回
expr
的总体标准方差。它将行视为整个总体,而不是样本,因此它以行数作为分母。您也可以使用VARIANCE()
,它是等效的,但不是标准 SQL。如果没有匹配的行,或者
expr
为NULL
,则VAR_POP()
返回NULL
。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述。返回
expr
的样本方差。也就是说,分母是行数减一。如果没有匹配的行,或者
expr
为NULL
,则VAR_SAMP()
返回NULL
。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述。返回
expr
的总体标准方差。VARIANCE()
是标准 SQL 函数VAR_POP()
的同义词,作为 MySQL 扩展提供。如果没有匹配的行,或者
expr
为NULL
,则VARIANCE()
返回NULL
。如果存在
over_clause
,则此函数将作为窗口函数执行。over_clause
的描述如 第 14.20.2 节“窗口函数概念和语法” 中所述。