您好,欢迎访问一九零五行业门户网

MySQL基础教程13 — 函数之与GROUP BY子句同时使用的函数

1. group by(聚合)函数本章论述了用于一组数值操作的 group (集合)函数。除非另作说明, group 函数会忽略 null 值。
假如你在一个不包含 roup by子句的语句中使用一个 group函数 ,它相当于对所有行进行分组。
avg([distinct] expr)
返回expr 的平均值。 distinct 选项可用于返回 expr的不同值的平均值。
若找不到匹配的行,则avg()返回 null 。
mysql> select student_name, avg(test_score) -> from student -> group by student_name;
bit_and(expr)
返回expr中所有比特的 bitwise and 。计算执行的精确度为64比特(bigint) 。
若找不到匹配的行,则这个函数返回 18446744073709551615 。(这是无符号 bigint 值,所有比特被设置为 1)。
bit_or(expr)
返回expr 中所有比特的bitwise or。计算执行的精确度为64比特(bigint) 。
若找不到匹配的行,则函数返回 0 。
bit_xor(expr)
返回expr 中所有比特的bitwise xor。计算执行的精确度为64比特(bigint) 。
若找不到匹配的行,则函数返回 0 。
count(expr)
返回select语句检索到的行中非null值的数目。
若找不到匹配的行,则count() 返回 0 。
mysql> select student.student_name,count(*)-> from student,course -> where student.student_id=course.student_id-> group by student_name;
count(*) 的稍微不同之处在于,它返回检索行的数目, 不论其是否包含 null值。
select 从一个表中检索,而不检索其它的列,并且没有 where子句时, count(*)被优化到最快的返回速度。例如:
mysql> select count(*) from student;
这个优化仅适用于 myisam表, 原因是这些表类型会储存一个函数返回记录的精确数量,而且非常容易访问。对于事务型的存储引擎(innodb, bdb), 存储一个精确行数的问题比较多,原因是可能会发生多重事物处理, 而每个都可能会对行数产生影响。
count(distinct expr,[expr...])
返回不同的非null值数目。
若找不到匹配的项,则count(distinct)返回 0 。
mysql> select count(distinct results) from student;
在mysql中, 你通过给定一个表达式列表而获取不包含null 不同表达式组合的数目。在标准 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;
or:
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系统变量,你可以设置允许的最大长度。 程序中进行这项操作的语法如下,其中 val 是一个无符号整数:
set [session | global] group_concat_max_len = val;
若已经设置了最大长度, 则结果被截至这个最大长度。
min([distinct] expr), max([distinct] expr)
返回expr 的最小值和最大值。 min() 和 max() 的取值可以是一个字符串参数;在这些情况下, 它们返回最小或最大字符串值。distinct关键词可以被用来查找expr 的不同值的最小或最大值,然而,这产生的结果与省略distinct 的结果相同。
若找不到匹配的行,min()和max()返回 null 。
mysql> select student_name, min(test_score), max(test_score)-> from student-> group by student_name;
对于min()、 max()和其它集合函数, mysql当前按照它们的字符串值而非字符串在集合中的相关位置比较 enum和set 列。这同order by比较二者的方式有所不同。这一点应该在mysql的未来版本中得到改善。
std(expr) stddev(expr)
返回expr 的总体标准偏差。这是标准 sql 的延伸。这个函数的stddev() 形式用来提供和oracle 的兼容性。可使用标准sql函数 stddev_pop() 进行代替。
若找不到匹配的行,则这些函数返回 null 。
stddev_pop(expr)
返回expr 的总体标准偏差(var_pop()的平方根)。你也可以使用 std() 或stddev(), 它们具有相同的意义,然而不是标准的 sql。
若找不到匹配的行,则stddev_pop()返回 null。
stddev_samp(expr)
返回expr 的样本标准差 ( var_samp()的平方根)。
若找不到匹配的行,则stddev_samp() 返回 null 。
sum([distinct] expr)
返回expr 的总数。 若返回集合中无任何行,则 sum() 返回null。distinct 关键词可用于 mysql 5.1 中,求得expr不同值的总和。
若找不到匹配的行,则sum()返回 null。
var_pop(expr)
返回expr 总体标准方差。它将行视为总体,而不是一个样本, 所以它将行数作为分母。你也可以使用 variance(),它具有相同的意义然而不是 标准的 sql。
若找不到匹配的项,则var_pop()返回null。
var_samp(expr)
返回expr 的样本方差。更确切的说,分母的数字是行数减去1。
若找不到匹配的行,则var_samp()返回null。
variance(expr)
返回expr 的总体标准方差。这是标准sql 的延伸。可使用标准sql 函数 var_pop() 进行代替。
若找不到匹配的项,则variance()返回null。
2. group by修改程序group by子句允许一个将额外行添加到简略输出端 with rollup 修饰符。这些行代表高层(或高聚集)简略操作。rollup 因而允许你在多层分析的角度回答有关问询的问题。例如,它可以用来向olap (联机分析处理) 操作提供支持。
设想一个名为sales 的表具有年份、国家、产品及记录销售利润的利润列:
create table sales ( year int not null, country varchar(20) not null, product varchar(32) not null, profit int );
可以使用这样的简单group by,每年对表的内容做一次总结:
mysql> select year, sum(profit) from sales group by year;+------+-------------+ | year | sum(profit) | +------+-------------+ | 2000 | 4525 | | 2001 | 3010 | +------+-------------+
这个输出结果显示了每年的总利润, 但如果你也想确定所有年份的总利润,你必须自己累加每年的单个值或运行一个加法询问。
或者你可以使用 rollup, 它能用一个问询提供双层分析。将一个 with rollup修饰符添加到group by 语句,使询问产生另一行结果,该行显示了所有年份的总价值:
mysql> select year, sum(profit) from sales group by year with rollup;+------+-------------+ | year | sum(profit) | +------+-------------+ | 2000 | 4525 | | 2001 | 3010 | | null | 7535 | +------+-------------+
总计高聚集行被年份列中的null值标出。
当有多重 group by 列时,rollup产生的效果更加复杂。这时,每次在除了最后一个分类列之外的任何列出现一个 “break” (值的改变) ,则问讯会产生一个高聚集累计行。
例如,在没有 rollup的情况下,一个以年、国家和产品为基础的关于 sales 表的一览表可能如下所示:
mysql> select year, country, product, sum(profit)-> from sales-> group by year, country, product; +------+---------+------------+-------------+ | year | country | product | sum(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 | +------+---------+------------+-------------+
表示总值的输出结果仅位于年/国家/产品的分析级别。当添加了 rollup后, 问询会产生一些额外的行:
mysql> select year, country, product, sum(profit) -> from sales -> group by year, country, product with rollup;+------+---------+------------+-------------+ | year | country | product | sum(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 | +------+---------+------------+-------------+
对于这个问询, 添加rollup 子句使村输出结果包含了四层分析的简略信息,而不只是一个下面是怎样解释 rollup输出:
一组给定的年份和国家的每组产品行后面, 会产生一个额外的总计行, 显示所有产品的总值。这些行将产品列设置为 null。
一组给定年份的行后面,会产生一个额外的总计行,显示所有国家和产品的总值。这些行将国家和产品列设置为 null。
最后, 在所有其它行后面,会产生一个额外的总计列,显示所有年份、国家及产品的总值。 这一行将年份、国家和产品列设置为 null。
使用rollup 时的其它注意事项
以下各项列出了一些mysql执行rollup的特殊状态:
当你使用 rollup时, 你不能同时使用 order by子句进行结果排序。换言之, rollup 和order by 是互相排斥的。然而,你仍可以对排序进行一些控制。在 mysql中, group by 可以对结果进行排序,而且你可以在group by列表指定的列中使用明确的 asc和desc关键词,从而对个别列进行排序。 (不论如何排序被rollup添加的较高级别的总计行仍出现在它们被计算出的行后面)。
limit可用来限制返回客户端的行数。limit 用在 rollup后面, 因此这个限制 会取消被rollup添加的行。例如:
mysql> select year, country, product, sum(profit) -> from sales -> group by year, country, product with rollup -> limit 5;+------+---------+------------+-------------+ | year | country | product | sum(profit) | +------+---------+------------+-------------+ | 2000 | finland | computer | 1500 | | 2000 | finland | phone | 100 | | 2000 | finland | null | 1600 | | 2000 | india | calculator | 150 | | 2000 | india | computer | 1200 | +------+---------+------------+-------------+
将rollup同 limit一起使用可能会产生更加难以解释的结果,原因是对于理解高聚集行,你所掌握的上下文较少。
在每个高聚集行中的null 指示符会在该行被送至客户端时产生。服务器会查看最左边的改变值后面的group by子句指定的列。对于任何结果集合中的,有一个词匹配这些名字的列, 其值被设为 null。(若你使用列数字指定了分组列,则服务器会通过数字确定将哪个列设置为 null)。
由于在高聚集行中的 null值在问询处理阶段被放入结果集合中,你无法将它们在问询本身中作为null值检验。例如,你无法将 having product is null 添加到问询中,从而在输出结果中删去除了高聚集行以外的部分。
另一方面, null值在客户端不以 null 的形式出现, 因而可以使用任何mysql客户端编程接口进行检验。
3. 具有隐含字段的group bymysql 扩展了 group by的用途,因此你可以使用select 列表中不出现在group by语句中的列或运算。这代表 “对该组的任何可能值 ”。你可以通过避免排序和对不必要项分组的办法得到它更好的性能。例如,在下列问询中,你无须对customer.name 进行分组:
mysql> select order.custid, customer.name, max(payments) -> from order,customer -> where order.custid = customer.custid -> group by order.custid;
在标准sql中, 你必须将 customer.name添加到 group by子句中。在mysql中, 假如你不在ansi模式中运行,则这个名字就是多余的。
假如你从 group by 部分省略的列在该组中不是唯一的,那么不要使用这个功能! 你会得到非预测性结果。
在有些情况下,你可以使用min()和max() 获取一个特殊的列值,即使他不是唯一的。下面给出了来自包含排序列中最小值的列中的值:
substr(min(concat(rpad(sort,6,' '),column)),7)
注意,假如你正在尝试遵循标准 sql, 你不能使用group by或 order by子句中的表达式。你可以通过使用表达式的别名绕过这一限制:
mysql> select id,floor(value/100) as val -> from tbl_name -> group by id, val order by val;
然而, mysql允许你使用group by 及 order by 子句中的表达式。例如:
mysql> select id, floor(value/100) from tbl_name order by rand();
以上就是mysql基础教程13 —— 函数之与group by子句同时使用的函数的内容。
其它类似信息

推荐信息