14.19.1 聚合函数说明
本节描述操作值集的聚合函数。它们通常与GROUP BY
子句一起使用,以将值分组到子集中。
表14.29 聚合函数
Name | Description |
---|---|
AVG() |
返回参数的平均值 |
BIT_AND() |
返回位元AND |
BIT_OR() |
返回位元OR |
BIT_XOR() |
返回位元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
值,转换操作将使用 underlying 数字值。
BIT_AND()、BIT_OR()和BIT_XOR()聚合函数执行位运算。
MySQL 位函数和操作符允许二进制字符串类型参数(BINARY
、VARBINARY
和BLOB
类型),并返回与之相似的值,这使得它们可以处理大于64位的参数和结果。关于位运算的参数评估和结果类型讨论,请参见第14.12节,“位函数和操作符”的介绍部分。
-
AVG([DISTINCT]
expr
) [over_clause
]返回
的平均值。可以使用expr
DISTINCT
选项,返回expr
的唯一值的平均值。如果没有匹配行,
AVG()
返回NULL
。函数也会返回NULL
,如果expr
为NULL
。如果存在
over_clause
,函数执行为窗口函数。over_clause
在第14.20.2节,“窗口函数概念和语法”中有描述;不能与DISTINCT
一起使用。mysql> SELECT student_name, AVG(test_score) FROM student GROUP BY student_name;
-
返回
expr
中的所有位的逻辑与结果。函数结果类型取决于函数参数是否被评估为二进制字符串或数字:
-
二进制字符串评估发生在参数值具有二进制字符串类型,且参数不是十六进制字面量、位字面量或
NULL
字面量时。否则,进行数值评估,并将参数值转换为无符号64位整数以满足需求。 -
二进制字符串评估生成与参数值相同长度的二进制字符串。如果参数值长度不等,出现
ER_INVALID_BITWISE_OPERANDS_SIZE
错误。如果参数值大小超过511字节,出现ER_INVALID_BITWISE_AGGREGATE_OPERANDS_SIZE
错误。数值评估生成无符号64位整数。
如果没有匹配行,
BIT_AND()
返回与参数值相同长度的中性值(所有位设置为1)。NULL
值除非所有值都是NULL
,否则不影响结果。在这种情况下,结果也是与参数值相同长度的中性值。关于参数评估和结果类型的更多信息,请参阅第14.12节,“位函数和操作符”的介绍讨论。
BIT_AND()
在mysql客户端中被调用时,二进制字符串结果以十六进制表示,取决于--binary-as-hex
选项的值。关于该选项的更多信息,请参见第6.5.1节,“mysql — MySQL 命令行客户端”。如果存在
over_clause
,该函数将以窗口函数执行。over_clause
在第14.20.2节,“窗口函数概念和语法”中有描述。 -
-
BIT_OR(
expr
) [over_clause
]返回
OR
操作符对所有位的结果。结果类型取决于函数参数是否被评估为二进制字符串或数字:
-
当参数值具有二进制字符串类型,且不是十六进制字面量、位字面量或
NULL
字面量时,进行二进制字符串评估。否则,以必要转换为无符号64位整数进行数字评估。 -
二进制字符串评估产生与参数值相同长度的二进制字符串。如果参数值不等长,出现
ER_INVALID_BITWISE_OPERANDS_SIZE
错误。如果参数值大小超过511字节,出现ER_INVALID_BITWISE_AGGREGATE_OPERANDS_SIZE
错误。数值评估产生无符号64位整数。
如果没有匹配行,
BIT_OR()
返回中性值(所有比特设置为0),与参数值相同长度。NULL
值除非所有值都是NULL
,否则不影响结果。在这种情况下,结果也是与参数值相同长度的中性值。关于参数评估和结果类型的更多信息,请参阅第14.12节,“比特函数和操作符”的介绍讨论。
BIT_OR()
在mysql 客户端中被调用时,二进制字符串结果以十六进制表示,取决于--binary-as-hex
选项的值。关于该选项的更多信息,请参见第6.5.1节,“mysql — MySQL 命令行客户端”。如果存在
over_clause
,该函数将以窗口函数执行。over_clause
在第14.20.2节,“窗口函数概念和语法”中有描述。 -
-
BIT_XOR(
expr
) [over_clause
]返回
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 — The MySQL Command-Line Client”.如果存在
over_clause
,该函数将以窗口函数执行。over_clause
在第14.20.2节,“窗口函数概念和语法”中有描述。 -
-
返回
SELECT
语句检索行中的非空值的个数。结果是一个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(*)
语句只统计当前事务可见的行。SELECT COUNT(*) FROM
查询对tbl_name
InnoDB
表的性能优化,假设没有额外的子句,如WHERE
或GROUP BY
,适用于单线程工作负载。InnoDB
通过遍历最小可用的次要索引处理SELECT COUNT(*)
语句,除非索引或优化器提示使用不同的索引。如果没有次要索引,InnoDB
则通过扫描聚集索引处理SELECT COUNT(*)
语句。如果索引记录不完全在缓冲池中,处理
SELECT COUNT(*)
语句需要一些时间。为了更快的计数,可以创建一个计数表,让应用程序根据插入和删除操作更新它。但是在同一个计数表上有成千个并发事务更新的情况下,这种方法可能不太好用。如果只需要近似行数,使用SHOW TABLE STATUS
。InnoDB
对SELECT COUNT(*)
和SELECT COUNT(1)
操作处理方式相同,没有性能差异。对于
MyISAM
表,COUNT(*)
如果只从一个表中检索,不检索其他列,没有WHERE
子句,返回结果非常快。例如:mysql> SELECT COUNT(*) FROM student;
这个优化只适用于
MyISAM
表,因为该存储引擎中存储了精确的行数,可以快速访问。COUNT(1)
只有在第一个列定义为NOT NULL
时才会被优化。 -
COUNT(DISTINCT
expr
,[expr
...])返回不同非空
expr
值的行数。如果没有匹配行,
COUNT(DISTINCT)
返回0
.mysql> SELECT COUNT(DISTINCT results) FROM student;
在 MySQL 中,您可以通过给出表达式列表来获得不包含空值的表达式组合数。在标准 SQL 中,您需要将所有表达式嵌套在
COUNT(DISTINCT ...)
中。 -
这个函数返回一个字符串结果,包含组中的非空值。它返回
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
子句。要以降序顺序排序,添加DESC
(降序)关键字到ORDER BY
子句中指定的列名中。默认是升序顺序;可以使用ASC
关键字来指定。默认分隔符为逗号(,
)。要指定分隔符,可以使用SEPARATOR
后跟字符串字面量值,插入组值之间。要消除分隔符,指定SEPARATOR ''
。结果将被截断到由
group_concat_max_len
系统变量指定的最大长度,该变量默认值为 1024。该值可以设置更高,但是返回值的实际最大长度受max_allowed_packet
变量的值限制。修改group_concat_max_len
变量的语法为,whereval
是一个无符号整数: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命令行客户端”。 -
JSON_ARRAYAGG(
col_or_expr
) [over_clause
]将结果集聚合为一个
JSON
数组,该数组的元素由行组成。该数组的顺序是未定义的。如果col_or_expr
为NULL
,函数返回一个JSON[null]
元素数组。如果结果集为空或出现错误,函数返回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)
重复键处理 当该函数的结果被 normalize 时,具有重复键值将被丢弃。遵循MySQL
JSON
数据类型规范不允许重复键,只使用最后遇到的值与该键在返回对象中(“最后一个重复键获胜”)。这意味着,使用该函数对SELECT语句中的列结果可能取决于行的顺序,这并不是确定的。当作窗口函数时,如果frame中存在重复键,只有最后一个值在结果中出现。frame中的最后一行的值是确定的,如果
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
(通常无论如何都会强制排序),并且你想要指定某个键顺序,可以将JSON_OBJECTAGG()
作为窗口函数,包括一个OVER
子句,使用ORDER BY
语句来对框架行强制排序。以下几个不同的框架规范的示例展示了有和无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值的 normalization、合并和自动包装,了解更多信息和示例。
-
MAX([DISTINCT]
expr
) [over_clause
]返回
expr
的最大值。MAX()
可以接受字符串参数,在这种情况下,它返回最大字符串值。见第10.3.1节,“MySQL索引使用方法”。可以使用DISTINCT
关键字来找到expr
的最大distinct值,但是这与省略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()
是MySQL扩展的标准SQL函数STDDEV_POP()
的同义词。如果没有匹配行,或者
expr
为NULL
,STD()
返回NULL
。如果存在
over_clause
,STD()
将作为窗口函数执行。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
。如果存在窗口函数子句,
SUM()
执行为窗口函数。窗口函数子句在第14.20.2节,“窗口函数概念和语法”中有描述;不能与DISTINCT
关键字一起使用。 -
返回
expr
的总体标准方差。它将行视为整个样本,否则使用行数作为分母。你也可以使用VARIANCE()
如果没有匹配行,或者
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()
是MySQL扩展的标准SQL函数VAR_POP()
的同义词。如果没有匹配的行,或者
expr
为NULL
,VARIANCE()
返回NULL
。如果存在
over_clause
,这个函数将以窗口函数执行。over_clause
在第14.20.2节,“窗口函数概念和语法”中有描述。