10.1 数据分组
使用分组可以将数据分为多个逻辑组,对每个组进行聚集计算。
10.2 创建分组
使用SELECT语句的GROUP BY子句建立分组。
- GROUP BY子句必须出现在WHERE之后,ORDER BY子句之前。
- GROUP BY子句可以包含任意数目的列,可以对分组进行嵌套。
- 如果GUOUP BY子句中嵌套了分组,数据将在最后指定的分组上进行汇总。
- GUOUP BY子句中的列必须是实际有效的检索列或表达式,不能使用别名。
- 除聚集计算语句外,SELECT语句中的每一列都必须在GROUP BY子句中给出。
- 一行或多行NULL值,将作为一个分组返回。
某些DBMS允许根据SELECT列表中的相对位置指定列,但不建议使用,容易导致编辑SQL语句时出错。
对每个vent_id而不是整个表计算num_prods,
SELECT vend_id, COUNT(*) AS num_prods
FROM Products
GROUP BY vend_id;
可以看出,供应商BRS01有三个产品
vend_id | num_prods
BRS01 | 3
DLL01 | 4
FNG01 | 2
10.3 过滤分组
使用HAVING子句可以过滤分组。
相比之下,WHERE子句过滤指定的是行而不是分组。也可以理解为: WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤。
HAVING子句支持所有WHERE操作符,也就是说有关WHERE的句法都适用于HAVING,只是关键字可能有差别。
SELECT cust_id, COUNT(*) AS orders FROM Orders
GROUP BY cust_id
HAVING COUNT(*) >=2;
按cust_id分组,计算每个分组cust_id的订单数量,
过滤订单数量>=2的分组
同时使用WHERE子句和HAVING子句
列出具有两个以上商品且价格>=4的供应商
SELECT vend_id, COUNT(*) AS num_prods
FROM Products
WHERE prod_price >= 4
GROUP BY vend_id
HAVING COUNT(*) >=2;
WHERE子句过滤价格>=4的商品,然后按照vent_id分组,HAVING子句过滤计数>=的分组。
vend_id | num_prods
BRS01 |3
FNG01 |2
10.4 分组和排序
对比GROUP BY 与 ORDER BY
GROUP BY | OREDR BY |
输出可能不是分组的顺序 | 对产生的输出排序 |
只能使用选择列或表达式列,而且必须使用每个选择列表达式 | 任意列都可以使用,包括非选择列 |
必须使用与聚集函数一起的列或表达式 | 不一定需要 |
GROUP BY子句的分组数据输出并不一定是顺序的,输出的顺序也不一定满足实际的需要,所以千万不要仅仅依赖GROUP BY排序数据。
一般在使用GROUP BY子句的同时也使用ORDER BY子句,保证数据正确排序,满足实际需要。
SELECT order_num, COUNT(*) AS items
FROM OrderItems
GROUP BY order_num HAVING COUNT(*) >= 3
ORDER BY items, order_num;
order_num | items
20006 |3
20009 |3
20007 |5
20008 |5
10.5 SELECT子句顺序
在SELECT语句中使用子句时,必须遵循的次序。
子句 | 说明 | 是否必须使用 |
SELECT | 要返回的列或表达式 | 是 |
FROM | 从表中检索数据 | 仅在从表选择数据时使用 |
WHERE | 行过滤 | 否 |
GROUP BY | 分组 | 仅在按组计算聚集时使用 |
HAVING | 组过滤 | 否 |
ORDER BY | 输出排序 | 否 |