Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  Aggregate Function Descriptions

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值,返回近似值参数(FLOATDOUBLE)的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()这样期望数字参数的函数,如果必要,会将参数转换为数字。对于SETENUM值,转换操作将使用 underlying 数字值。

BIT_AND()、BIT_OR()和BIT_XOR()聚合函数执行位运算。

MySQL 位函数和操作符允许二进制字符串类型参数(BINARYVARBINARYBLOB类型),并返回与之相似的值,这使得它们可以处理大于64位的参数和结果。关于位运算的参数评估和结果类型讨论,请参见第14.12节,“位函数和操作符”的介绍部分。

  • AVG([DISTINCT] expr) [over_clause]

    返回expr的平均值。可以使用DISTINCT选项,返回expr的唯一值的平均值。

    如果没有匹配行,AVG()返回NULL。函数也会返回NULL,如果exprNULL

    如果存在over_clause,函数执行为窗口函数。over_clause第14.20.2节,“窗口函数概念和语法”中有描述;不能与DISTINCT一起使用。

    mysql> SELECT student_name, AVG(test_score)
           FROM student
           GROUP BY student_name;
  • BIT_AND(expr) [over_clause]

    返回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节,“窗口函数概念和语法”中有描述。

  • COUNT(expr) [over_clause]

    返回SELECT语句检索行中的非空值的个数。结果是一个BIGINT值。

    如果没有匹配的行,COUNT()返回0COUNT(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表的性能优化,假设没有额外的子句,如WHEREGROUP BY,适用于单线程工作负载。

    InnoDB通过遍历最小可用的次要索引处理SELECT COUNT(*)语句,除非索引或优化器提示使用不同的索引。如果没有次要索引,InnoDB则通过扫描聚集索引处理SELECT COUNT(*)语句。

    如果索引记录不完全在缓冲池中,处理SELECT COUNT(*)语句需要一些时间。为了更快的计数,可以创建一个计数表,让应用程序根据插入和删除操作更新它。但是在同一个计数表上有成千个并发事务更新的情况下,这种方法可能不太好用。如果只需要近似行数,使用SHOW TABLE STATUS

    InnoDBSELECT 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 ...)中。

  • GROUP_CONCAT(expr)

    这个函数返回一个字符串结果,包含组中的非空值。它返回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变量的语法为,where val是一个无符号整数:

    SET [GLOBAL | SESSION] group_concat_max_len = val;

    返回值是一个非二进制或二进制字符串,取决于参数是否是非二进制或二进制字符串。结果类型为TEXTBLOB,除非group_concat_max_len小于或等于512,在这种情况下结果类型为VARCHARVARBINARY

    如果在mysql客户端中调用GROUP_CONCAT(),二进制字符串结果将使用十六进制表示,取决于--binary-as-hex的值。关于该选项的更多信息,请见第6.5.1节,“MySQL命令行客户端”

    详见CONCAT()CONCAT_WS()第14.8节,“字符串函数和操作符”

  • JSON_ARRAYAGG(col_or_expr) [over_clause]

    将结果集聚合为一个JSON数组,该数组的元素由行组成。该数组的顺序是未定义的。如果col_or_exprNULL,函数返回一个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 时,具有重复键值将被丢弃。遵循MySQLJSON数据类型规范不允许重复键,只使用最后遇到的值与该键在返回对象中(“最后一个重复键获胜”)。这意味着,使用该函数对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相同结果。

    如果没有匹配行,或者exprNULLMAX() 返回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当前将ENUMSET列比较为字符串值,而不是根据在集中的相对位置。与ORDER BY的比较方式不同。

  • MIN([DISTINCT] expr) [over_clause]

    返回expr的最小值。MIN() 可以接收字符串参数,在这种情况下,它返回最小的字符串值。请参阅第10.3.1节,“MySQL索引使用方法”。可以使用DISTINCT关键字来找到expr的最小值,但是这与省略DISTINCT相同结果。

    如果没有匹配行,或者exprNULLMIN()返回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当前将ENUMSET列比较为字符串值,而不是根据字符串在集合中的相对位置。这与ORDER BY的比较方式不同。

  • STD(expr) [over_clause]

    返回expr的样本标准差。STD()是MySQL扩展的标准SQL函数STDDEV_POP()的同义词。

    如果没有匹配行,或者exprNULLSTD()返回NULL

    如果存在over_clauseSTD()将作为窗口函数执行。over_clause第14.20.2节,“窗口函数概念和语法”中有描述。

  • STDDEV(expr) [over_clause]

    返回expr的样本标准差。STDDEV()是标准SQL函数STDDEV_POP()的同义词,为兼容Oracle提供。

    如果没有匹配行,或者exprNULLSTDDEV()返回NULL

    如果存在over_clause,该函数将作为窗口函数执行。over_clause第14.20.2节,“窗口函数概念和语法”中有描述。

  • STDDEV_POP(expr) [over_clause]

    返回expr的样本标准差(VAR_POP()的平方根)。你也可以使用STD()STDDEV(),它们等价,但不是标准SQL。

    如果没有匹配的行,或者exprNULLSTDDEV_POP()返回NULL

    如果存在over_clause,该函数将作为窗口函数执行。over_clause第14.20.2节,“窗口函数概念和语法”中有描述。

  • STDDEV_SAMP(expr) [over_clause]

    返回expr的样本标准差(VAR_SAMP()的平方根。

    如果没有匹配的行,或者exprNULLSTDDEV_SAMP()返回NULL

    如果存在over_clause,该函数将作为窗口函数执行。over_clause第14.20.2节,“窗口函数概念和语法”中有描述。

  • SUM([DISTINCT] expr) [over_clause]

    返回expr的和。返回集没有行时,SUM()返回NULL。可以使用DISTINCT关键字,只对expr的唯一值求和。

    如果没有匹配行,或者exprNULLSUM()返回NULL

    如果存在窗口函数子句,SUM()执行为窗口函数。窗口函数子句在第14.20.2节,“窗口函数概念和语法”中有描述;不能与DISTINCT关键字一起使用。

  • VAR_POP(expr) [over_clause]

    返回expr的总体标准方差。它将行视为整个样本,否则使用行数作为分母。你也可以使用VARIANCE()

    如果没有匹配行,或者exprNULLVAR_POP()返回NULL

    如果存在over_clause,该函数将作为窗口函数执行。over_clause第14.20.2节,“窗口函数概念和语法”中有描述。

  • VAR_SAMP(expr) [over_clause]

    返回expr的样本方差,即分母是行数减一。

    如果没有匹配行或exprNULLVAR_SAMP()返回NULL.

    如果存在over_clause,该函数将作为窗口函数执行。over_clause第14.20.2节,“窗口函数概念和语法”中有描述。

  • VARIANCE(expr) [over_clause]

    返回expr的总体标准方差。VARIANCE()是MySQL扩展的标准SQL函数VAR_POP()的同义词。

    如果没有匹配的行,或者exprNULLVARIANCE()返回NULL

    如果存在over_clause,这个函数将以窗口函数执行。over_clause第14.20.2节,“窗口函数概念和语法”中有描述。