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

输出排序