本文将介绍如何分组数据,以便能汇总表内容的子集。这涉及两个新SELECT语句子句,分别是GROUP BY子句和HAVING子句。
分组允许把数据分为多个逻辑组,以便能对每个组进行聚集计算
1、创建分组
分组是在SELECT语句的GROUP BY子句中建立的。 先看一个例子:
mysql> select vend_id,count(*) as num_prods
-> from products
-> group by vend_id;
上面的SELECT语句指定了两个列, vend_id包含产品供应商的ID,num_prods为计算字段(用COUNT(*)函数建立)。 GROUP BY子句指示MySQL按vend_id排序并分组数据。这导致对每个vend_id而不是整个表计算num_prods一次。
在具体使用GROUP BY子句前,需要知道一些重要的规定。
GROUP BY子句可以包含任意数目的列。这使得能对分组进行嵌套,为数据分组提供更细致的控制。
如果在GROUP BY子句中嵌套了分组,数据将在最后规定的分组上进行汇总。换句话说,在建立分组时,指定的所有列都一起计算(所以不能从个别的列取回数据)。
GROUP BY子句中列出的每个列都必须是检索列或有效的表达式(但不能是聚集函数)。如果在SELECT 中使用表达式,则必须在GROUP BY子句中指定相同的表达式。不能使用别名。
除聚集计算语句外, SELECT语句中的每个列都必须在GROUP BY子句中给出。
如果分组列中具有NULL值,则NULL将作为一个分组返回。如果列中有多行NULL值,它们将分为一组。
GROUP BY子句必须出现在WHERE子句之后, ORDER BY子句之前。
2、过滤分组
除了能用GROUP BY分组数据外, MySQL还允许过滤分组,规定包括哪些分组,排除哪些分组。
HAVING非常类似于WHERE。事实上,目前为止所学过的所有类型的WHERE子句都可以用HAVING来替代。唯一的差别是WHERE过滤行,而HAVING过滤分组。
mysql> select cust_id,count(*) as orders
-> from orders
-> group by cust_id
-> having count(*)>=2;
3、分组和排序
虽然GROUP BY和ORDER BY经常完成相同的工作,但它们是非常不同的。下表汇总了它们之间的差别。
order by | group by |
排序产生的输出 | 分组行,但输出可能不是分组的顺序 |
任意列都可以使用 | 只可能使用选择列或表达式列,而且必须使用每个选择列表达式 |
不一定需要 | 如果与聚集函数一起使用列(或表达式),则必须使用 |
先看一个例子:
下面的SELECT语句类似于前面那些例子。它检索总计订单价格大于等于50的订单的订单号和总计订单价格:
mysql> select order_num,sum(quantity*item_price) as ordertotal
-> from orderitems
-> group by order_num
-> having sum(quantity*item_price)>=50;
为按总计订单价格排序输出,需要添加ORDER BY子句,如下所示:
mysql> select order_num,sum(quantity*item_price) as ordertotal
-> from orderitems
-> group by order_num
-> having sum(quantity*item_price)>=50
-> order by ordertotal;
4、select子句顺序
下表以在SELECT语句中使用时必须遵循的次序,列出迄今为止所学过的子句。
子句 | 说明 | 是否必须使用 |
select | 要返回的列或表达式 | 是 |
from | 从中检索数据的表 | 仅在从表选择数据时使用 |
where | 行级过滤 | 否 |
group by | 分组说明 | 仅在按组计算聚集时使用 |
having | 组级过滤 | 否 |
order by | 输出排序顺序 | 否 |
limit | 要检索的行数 | 否 |
Comments