查看“MySQL 函数和运算符:汇总函数”的源代码
←
MySQL 函数和运算符:汇总函数
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[category:MySQL]] == 关于 == 汇总函数(or 集合函数???)对值集进行操作。它们通常与“GROUP BY”子句一起使用以将值分组为子集。 {| class="wikitable" ! Name !! Description |- | '''AVG()''' || 返回参数的平均值 |- | BIT_AND() || 按位返回 AND |- | BIT_OR() || 按位返回 OR |- | BIT_XOR() || 返回按位异或 |- | '''COUNT()''' || 返回计数返回的行数 |- | '''COUNT(DISTINCT)''' || 返回多个不同值的计数 |- | GROUP_CONCAT() || 返回串联的字符串 |- | JSON_ARRAYAGG()(引入 5.7.22) || 将结果集作为单个 JSON 数组返回 |- | JSON_OBJECTAGG()(引入 5.7.22) || 将结果集作为单个 JSON 对象返回 |- | '''MAX()''' || 返回最大值 |- | '''MIN()''' || 返回最小值 |- | STD() || 返回人口标准差 |- | STDDEV() || 返回人口标准差 |- | STDDEV_POP() || 返回人口标准差 |- | STDDEV_SAMP() || 返回 sample 标准偏差 |- | '''SUM()''' || 返回总和 |- | VAR_POP() || 返回总体标准方差 |- | VAR_SAMP() || 返回 samples 方差 |- | VARIANCE() || 返回总体标准方差 |} 【说明:略】 == GROUP BY 【WITH ROLLUP】== “GROUP BY”子句允许使用“'''WITH ROLLUP'''”修饰符,该修饰符使摘要输出包括代表更高级别(即'''超级汇总''')摘要操作的额外行【???】。 ROLLUP 从而使您可以通过单个查询回答多个分析级别的问题。 : 例如,ROLLUP可用于提供对 OLAP(在线分析处理)操作的支持。 假设 salest 表具有 year,country,product 和 profit 列以记录销售获利能力: <syntaxhighlight lang="xml"> CREATE TABLE sales ( year INT, country VARCHAR(20), product VARCHAR(32), profit INT ); </syntaxhighlight> 要汇总每年的表格内容,请使用简单的 GROUP BY,如下所示: <syntaxhighlight lang="xml"> mysql> SELECT year, SUM(profit) AS profit FROM sales GROUP BY year; +------+--------+ | year | profit | +------+--------+ | 2000 | 4525 | | 2001 | 3010 | +------+--------+ </syntaxhighlight> 输出显示了每年的总(总计)利润。<br/> 要确定所有年份的总利润,您必须自己累加各个值或运行其他查询。或者,您可以使用 ROLLUP,它'''通过一个查询提供两个分析级别'''。在GROUP BY子句中添加“WITH ROLLUP”修饰符会使查询产生另一行(超级汇总),该行显示所有年份值的总计: <syntaxhighlight lang="xml"> mysql> SELECT year, SUM(profit) AS profit FROM sales GROUP BY year WITH ROLLUP; +------+--------+ | year | profit | +------+--------+ | 2000 | 4525 | | 2001 | 3010 | | NULL | 7535 | +------+--------+ </syntaxhighlight> '''year列中的NULL值标识总计超级总计行'''。 如果有多个“GROUP BY”列,则 ROLLUP 的作用更为复杂。在这种情况下,每当除最后一个分组列之外的任何其他列中的值发生变化时,查询都会产生一个额外的超级汇总摘要行。 例如,如果没有 ROLLUP,则基于 year,country 和 product 的 salest 表的摘要可能看起来像这样,其中输出仅指示分析的年份/国家/产品级别的摘要值: <syntaxhighlight lang="xml"> mysql> SELECT year, country, product, SUM(profit) AS profit FROM sales GROUP BY year, country, product; +------+---------+------------+--------+ | year | country | product | profit | +------+---------+------------+--------+ | 2000 | Finland | Computer | 1500 | | 2000 | Finland | Phone | 100 | | 2000 | India | Calculator | 150 | | 2000 | India | Computer | 1200 | | 2000 | USA | Calculator | 75 | | 2000 | USA | Computer | 1500 | | 2001 | Finland | Phone | 10 | | 2001 | USA | Calculator | 50 | | 2001 | USA | Computer | 2700 | | 2001 | USA | TV | 250 | +------+---------+------------+--------+ </syntaxhighlight> 添加 ROLLUP 后,查询将产生几行: <syntaxhighlight lang="xml"> mysql> SELECT year, country, product, SUM(profit) AS profit FROM sales GROUP BY year, country, product WITH ROLLUP; +------+---------+------------+--------+ | year | country | product | profit | +------+---------+------------+--------+ | 2000 | Finland | Computer | 1500 | | 2000 | Finland | Phone | 100 | | 2000 | Finland | NULL | 1600 | | 2000 | India | Calculator | 150 | | 2000 | India | Computer | 1200 | | 2000 | India | NULL | 1350 | | 2000 | USA | Calculator | 75 | | 2000 | USA | Computer | 1500 | | 2000 | USA | NULL | 1575 | | 2000 | NULL | NULL | 4525 | | 2001 | Finland | Phone | 10 | | 2001 | Finland | NULL | 10 | | 2001 | USA | Calculator | 50 | | 2001 | USA | Computer | 2700 | | 2001 | USA | TV | 250 | | 2001 | USA | NULL | 3000 | | 2001 | NULL | NULL | 3010 | | NULL | NULL | NULL | 7535 | +------+---------+------------+--------+ </syntaxhighlight> * 当超级汇总行中的NULL指示符发送到 Client 端时,它们就会产生。服务器查看在GROUP BY子句中命名的列,该列紧随其后的是更改了值的最左列。对于结果集中名称与任何名称匹配的任何列,其值均设置为NULL。 (如果您指定按列位置分组的列,则服务器会识别要按位置设置为NULL的列.)【???】 * 由于超级聚合行中的 NULL 值是在查询处理的最后阶段放入结果集中的,因此只能在选择列表或“HAVING”子句中将它们作为 NULL 值进行测试。您不能在连接条件中或 WHERE 子句中将它们测试为NULL值来确定要选择的行。 *: 例如,您不能将“WHERE product IS NULL”添加到查询中以从输出中消除除超级聚合行以外的所有行。 * NULL 的值在 Client 端确实显示为 NULL,并且可以使用任何 MySQLClient 端编程接口进行测试。但是,在这一点上,您无法区分 NULL 是表示常规分组值还是超汇总值。在 MySQL 8.0 中,可以使用“GROUPING()”函数测试区别。【???】 === 使用 ROLLUP 时的其他注意事项 === # 使用 ROLLUP 时,也不能使用 ORDER BY 子句对结果进行排序。换句话说,'''ROLLUP 和 ORDER BY 在 MySQL 中是互斥的。'''但是,您仍然可以控制排序顺序。要解决防止将 ROLLUP 与 ORDER BY 结合使用并实现特定的分组结果排序 Sequences 的限制,请生成分组结果集作为派生表并将 ORDER BY 应用于该表。例如: #: <syntaxhighlight lang="xml"> mysql> SELECT * FROM (SELECT year, SUM(profit) AS profit FROM sales GROUP BY year WITH ROLLUP) AS dt ORDER BY year DESC; +------+--------+ | year | profit | +------+--------+ | 2001 | 3010 | | 2000 | 4525 | | NULL | 7535 | +------+--------+ </syntaxhighlight> #: 在这种情况下,超级汇总摘要行将根据其进行计算的行进行排序,并且它们的位置取决于排序 Sequences(在开始时是升序排序,在结束时是降序排序)。【???】 # '''LIMIT'''可用于限制返回给 Client 端的行数。 LIMIT 在 ROLLUP 之后应用,因此该限制'''适用于 ROLLUP 添加的额外行'''。例如: #: <syntaxhighlight lang="xml"> mysql> SELECT year, country, product, SUM(profit) AS profit FROM sales GROUP BY year, country, product WITH ROLLUP LIMIT 5; +------+---------+------------+--------+ | year | country | product | profit | +------+---------+------------+--------+ | 2000 | Finland | Computer | 1500 | | 2000 | Finland | Phone | 100 | | 2000 | Finland | NULL | 1600 | | 2000 | India | Calculator | 150 | | 2000 | India | Computer | 1200 | +------+---------+------------+--------+ </syntaxhighlight> # MySQL 扩展允许在选择列表中命名不在 GROUP BY 列表中出现的列。在这种情况下,服务器可以从摘要行中的该未聚合的列中自由选择任何值,其中包括“WITH ROLLUP”添加的多余行。 #: 例如,在以下查询中,country 是未聚合的列,不会出现在 GROUP BY 列表中,并且为此列选择的值是不确定的: #: <syntaxhighlight lang="xml"> mysql> SELECT year, country, SUM(profit) AS profit FROM sales GROUP BY year WITH ROLLUP; +------+---------+--------+ | year | country | profit | +------+---------+--------+ | 2000 | India | 4525 | | 2001 | USA | 3010 | | NULL | USA | 7535 | +------+---------+--------+ </syntaxhighlight> #: 【那这结果没啥意义嘛?】 #* 当未启用“ONLY_FULL_GROUP_BY” SQL 模式时,允许此行为。如果启用了该模式,则由于 GROUP BY 子句中未列出 country,因此服务器将查询拒绝为非法。启用“ONLY_FULL_GROUP_BY”后,您仍然可以通过对非确定值列使用“'''ANY_VALUE()'''”函数来执行查询: #*: <syntaxhighlight lang="xml"> mysql> SELECT year, ANY_VALUE(country) AS country, SUM(profit) AS profit FROM sales GROUP BY year WITH ROLLUP; +------+---------+--------+ | year | country | profit | +------+---------+--------+ | 2000 | India | 4525 | | 2001 | USA | 3010 | | NULL | USA | 7535 | +------+---------+--------+ </syntaxhighlight> #*: 【???,还是没啥意义嘛?】 === MySQL 对 GROUP BY 的处理 === 【接上一节最后,MySQL如何处理“选择列表,HAVING条件 或 ORDER BY列表引用未在GROUP BY子句中命名的未聚合列”的查询】 SQL-92 和更早版本不允许选择列表,HAVING条件或ORDER BY列表引用未在GROUP BY子句中命名的未聚合列的查询。 : 例如,此查询在标准 SQL-92 中是非法的,因为选择列表中未聚合的name列未出现在GROUP BY中: : <syntaxhighlight lang="xml"> SELECT o.custid, c.name, MAX(o.payment) FROM orders AS o, customers AS c WHERE o.custid = c.custid GROUP BY o.custid; </syntaxhighlight> 为了使查询在 SQL-92 中合法,必须从选择列表中省略name列或在GROUP BY子句中命名。 SQL:1999 和更高版本允许在功能上依赖于GROUP BY列的每个非可选功能 T301 此类非聚合:如果name和custid之间存在这种关系,则查询合法。 : 例如,custid是customers的主键就是这种情况。 MySQL 5.7.5 及更高版本实现对功能依赖性的检测。如果启用了“ONLY_FULL_GROUP_BY” SQL 模式(默认情况下是默认设置),则 MySQL 拒绝选择列表,HAVING条件或ORDER BY列表引用未在GROUP BY子句中命名且在功能上不依赖于它们的未聚合列的查询。(在 5.7.5 之前,MySQL 不检测功能依赖关系,默认情况下未启用ONLY_FULL_GROUP_BY。) 启用ONLY_FULL_GROUP_BY SQL 模式时,MySQL 5.7.5 和更高版本还允许在GROUP BY子句中未命名的非聚合列,但前提是该列限于单个值,如以下示例所示: <syntaxhighlight lang="xml"> mysql> CREATE TABLE mytable ( -> id INT UNSIGNED NOT NULL PRIMARY KEY, -> a VARCHAR(10), -> b INT -> ); mysql> INSERT INTO mytable -> VALUES (1, 'abc', 1000), -> (2, 'abc', 2000), -> (3, 'def', 4000); mysql> SET SESSION sql_mode = sys.list_add(@@session.sql_mode, 'ONLY_FULL_GROUP_BY'); mysql> SELECT a, SUM(b) FROM mytable WHERE a = 'abc'; +------+--------+ | a | SUM(b) | +------+--------+ | abc | 3000 | +------+--------+ </syntaxhighlight> 使用ONLY_FULL_GROUP_BY时,也可能在SELECT列 table 中有多个非聚合列。在这种情况下,每个这样的列都必须限制为一个值,并且所有这样的限制条件必须由逻辑“AND”联接,如下所示: <syntaxhighlight lang="xml"> mysql> DROP TABLE IF EXISTS mytable; mysql> CREATE TABLE mytable ( -> id INT UNSIGNED NOT NULL PRIMARY KEY, -> a VARCHAR(10), -> b VARCHAR(10), -> c INT -> ); mysql> INSERT INTO mytable -> VALUES (1, 'abc', 'qrs', 1000), -> (2, 'abc', 'tuv', 2000), -> (3, 'def', 'qrs', 4000), -> (4, 'def', 'tuv', 8000), -> (5, 'abc', 'qrs', 16000), -> (6, 'def', 'tuv', 32000); mysql> SELECT @@session.sql_mode; +---------------------------------------------------------------+ | @@session.sql_mode | +---------------------------------------------------------------+ | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION | +---------------------------------------------------------------+ mysql> SELECT a, b, SUM(c) FROM mytable -> WHERE a = 'abc' AND b = 'qrs'; +------+------+--------+ | a | b | SUM(c) | +------+------+--------+ | abc | qrs | 17000 | +------+------+--------+ </syntaxhighlight> 如果禁用了“ONLY_FULL_GROUP_BY”,则对标准 SQL 使用GROUP BY的 MySQL 扩展允许选择列表,HAVING条件或ORDER BY列表引用未聚合的列,即使这些列在功能上不依赖于GROUP BY列也是如此。这使 MySQL 接受前面的查询。在这种情况下,服务器可以从每个组中自由选择任何值,因此,除非它们相同,否则选择的值是不确定的,这可能不是您想要的。 此外,通过添加ORDER BY子句不能影响每个组中值的选择。选择值之后,将进行结果集排序,并且ORDER BY不会影响服务器在每个组中选择哪个值。 * 禁用“ONLY_FULL_GROUP_BY”一般是有用的,因为您知道由于数据的某些属性,每个未聚合的列中在GROUP BY中未命名的所有值对于每个组都是相同的。 * 通过使用“ANY_VALUE()”引用未聚合的列,您可以在不禁用“ONLY_FULL_GROUP_BY”的情况下实现相同的效果。 下面的讨论演示了功能依赖性,不存在功能依赖性时 MySQL 产生的错误消息,以及在没有功能依赖性的情况下使 MySQL 接受查询的方法。<br/> 【。。。。。略。。。。。】 <syntaxhighlight lang="xml"> </syntaxhighlight> == 检测函数依赖性 == 【。。。。。略。。。。。】
返回至“
MySQL 函数和运算符:汇总函数
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
笔记
服务器
数据库
后端
前端
工具
《To do list》
日常
阅读
电影
摄影
其他
Software
Windows
WIKIOE
所有分类
所有页面
侧边栏
站点日志
工具
链入页面
相关更改
特殊页面
页面信息