10.4 分组和排序

GROUP BYORDER BY经常完成相同的工作,但它们非常不同,理解这一点很重要。表10-1汇总了它们之间的差别。

表10-1 ORDER BY与GROUP BY

ORDER BY GROUP BY
对产生的输出排序 对行分组,但输出可能不是分组的顺序
任意列都可以使用(甚至非选择的列也可以使用) 只可能使用选择列或表达式列,而且必须使用每个选择列表达式
不一定需要 如果与聚集函数一起使用列(或表达式),则必须使用

表10-1中列出的第一项差别极为重要。我们经常发现,用GROUP BY分组的数据确实是以分组顺序输出的。但并不总是这样,这不是SQL规范所要求的。此外,即使特定的DBMS总是按给出的GROUP BY子句排序数据,用户也可能会要求以不同的顺序排序。就因为你以某种方式分组数据(获得特定的分组聚集值),并不表示你需要以相同的方式排序输出。应该提供明确的ORDER BY子句,即使其效果等同于GROUP BY子句。

提示:不要忘记ORDER BY
一般在使用GROUP BY子句时,应该也给出ORDER BY子句。这是保证数据正确排序的唯一方法。千万不要仅依赖GROUP BY排序数据。

为说明GROUP BYORDER BY的使用方法,来看一个例子。下面的SELECT语句类似于前面那些例子。它检索包含三个或更多物品的订单号和订购物品的数目:

输入▼

  1. SELECT order_num, COUNT(*) AS items
  2. FROM OrderItems
  3. GROUP BY order_num
  4. HAVING COUNT(*) >= 3;

输出▼

  1. order_num items
  2. --------- -----
  3. 20006 3
  4. 20007 5
  5. 20008 5
  6. 20009 3

要按订购物品的数目排序输出,需要添加ORDER BY子句,如下所示:

输入▼

  1. SELECT order_num, COUNT(*) AS items
  2. FROM OrderItems
  3. GROUP BY order_num
  4. HAVING COUNT(*) >= 3
  5. ORDER BY items, order_num;

说明:Access的不兼容性
Microsoft Access不允许按别名排序,因此这个例子在Access中将失败。解决方法是用实际的计算或字段位置替换items(在ORDER BY子句中),即ORDER BY COUNT(*), order_numORDER BY 2, order_num

输出▼

  1. order_num items
  2. --------- -----
  3. 20006 3
  4. 20009 3
  5. 20007 5
  6. 20008 5

分析▼

在这个例子中,使用GROUP BY子句按订单号(order_num列)分组数据,以便COUNT(*)函数能够返回每个订单中的物品数目。HAVING子句过滤数据,使得只返回包含三个或更多物品的订单。最后,用ORDER BY子句排序输出。