1.数据分组
目前为止的所有计算都是在表的所有数据或匹配特定的WHERE子句的数据上进行的,如返回供应商DLL01提供的产品数目,输入:
SELECT COUNT(*) AS num_prods
FROM Products
WHERE vend_id = 'DLL01';
输出:
而使用分组可以将数据分为多个逻辑组,对每个分组进行聚集计算。
2.创建分组
使用SELECT语句的GROUP BY子句建立分组。
使用要点:
1)GROUP BY子句可以包含任意数目的列,因此可以对分组进行嵌套,进行更细致的数据分组。
2)若GROUP BY子句嵌套了分组,数据将在最后指定的分组上进行汇总。
3)GROUP BY子句中列出的每一列都必须是检索列或有效表达式,不能是聚集函数。若在SELECT中使用表达式,则必须在GROUP BY子句中指定相同的表达式。不能使用别名。
4)大多数SQL实现不允许GROUP BY列带有长度可变的数据类型。
5)除聚集计算外,SELECT语句中每一列都必须在GROUP BY子句中给出。
6)如果分组列中包含具有NULL值的行,则NULL将作为一个分组返回。若列中有多行NULL值,将分为一组。
7)GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。
输入:
SELECT vend_id, COUNT(*) AS num_prods
FROM Products
GROUP BY vend_id;
输出:
GROUP BY子句指示DBMS按vend_id排序并分组数据,这样对每个vend_id而不是整个表计算num_prods一次。
3.过滤分组
WHERE子句只能过滤指定行,要规定包括哪些分组,排除哪些分组,可以使用HAVING子句来过滤分组。HAVING支持所有的WHERE操作符。
输入:
SELECT cust_id, COUNT(*) AS orders
FROM Orders
GROUP BY cust_id
HAVING COUNT(*) >= 2;
输出:
过滤了COUNT(*) >= 2(两个以上订单)的分组。
同时使用WHERE和HAVING子句:假设想进一步过滤上面的语句,使其返回过去12个月内具有两个以上订单的顾客,可增加WHERE子句,过滤出过去12个月内具有两个以上订单的顾客,然后增加HAVING子句过滤出具有两个以上订单的分组。
为了列出具有两个以上产品且其价格大于等于4的供应商,输入:
SELECT vend_id, COUNT(*) AS num_prods
FROM Products
WHERE prod_price >= 4
GROUP BY vend_id
HAVING COUNT(*) >= 2;
输出:
如果没有WHERE子句,会多检索出一行(供应商DLL01,销售4个产品,价格都在4以下)。
输入:
SELECT vend_id, COUNT(*) AS num_prods
FROM Products
GROUP BY vend_id
HAVING COUNT(*) >= 2;
输出:
4.分组和排序
ORDER BY和GROUP BY
ORDER BY |
GROUP BY |
对产生的输出排序 |
对行分组,但输出可能不是分组的顺序 |
任意列都可以使用(甚至非选择的列也可以使用) |
只可能使用选择列或表达式列,而且必须使用每个选择列表达式 |
不一定需要 |
如果与聚集函数一起使用列(表达式),则必须使用 |
要保证数据正确的唯一方法是在使用GROUP BY子句的同时,应该也给出ORDER BY子句,不能依赖于GROUP BY排序数据。
为了检索包含三个或更多物品的订单号和订购物品的数目,输入:
SELECT order_num, COUNT(*) AS items
FROM OrderItems
GROUP BY order_num
HAVING COUNT(*) >= 3;
输出:
要按订购物品的数目排序输入,需要添加ORDER BY子句,输入:
SELECT order_num, COUNT(*) AS items
FROM OrderItems
GROUP BY order_num
HAVING COUNT(*) >= 3
ORDER BY items, order_num;
输出:
必须提供明确的ORDER BY子句,即使其效果等同于GROUP BY子句。
5.SELECT子句顺序
子句 |
说明 |
是否必须使用 |
SELECT |
要返回的列或表达式 |
是 |
FROM |
从中检索数据的表 |
仅从表选择数据时使用 |
WHERE |
行级过滤 |
否 |
GROUP BY |
分组说明 |
仅在按组进行聚集计算时使用 |
HAVING |
组级过滤 |
否 |
ORDER BY |
输出顺序排序 |
否 |