GROUP BY 子句

GROUP BY 子句将表分为几组。此子句通常与为每个这样的组生成总结值的聚集函数组合。编写 SELECT 语句中的某些示例显示了应用于整个表的聚集函数的用法。本章说明应用于行组的聚集函数。

使用不带聚集的 GROUP BY 子句与在 SELECT 子句中使用 DISTINCT(或 UNIQUE)关键字很相似。下列查询在选择特定列中描述。

图: 查询

SELECT DISTINCT customer_num FROM orders;
还可以按以下查询编写此语句。

图: 查询

SELECT customer_num FROM orders
          GROUP BY customer_num;
图 1图 2返回下列行。

图: 查询结果

customer_num
        
        101
        104
        106
        110
        ⋮
        124
        126
        127

GROUP BY 子句将行收集到组中,因此每一组中的每一行具有相同的客户号。在没有选择任何其它列的情况下,结束是唯一 customer_num 值的列表。

GROUP BY 子句的功能在将它与聚集函数配合使用时更明显。

下列查询检索每个订单的商品数和所有商品的总价。

图: 查询

SELECT order_num, COUNT (*) number, SUM (total_price) price
          FROM items
          GROUP BY order_num;

GROUP BY 子句导致 items 表的行数被收集为组,每个组由具有相同 order_num 值的行组成(即,将每个订单的商品收集在一起)。在数据库服务器构成组之后,就在每个组中应用聚集行数 COUNT 和 SUM 。

图 4对每一组返回每一行。它还使用标号来为 COUNT 和 SUM 表达式的结果提供名称,如下所示。

图: 查询结果

 order_num      number         price 
          
          1001           1          $250.00
          1002           2         $1200.00
          1003           3          $959.00
          1004           4         $1416.00
          ⋮
          1021           4         $1614.00
          1022           3          $232.00
          1023           6          $824.00

该结果将 items 表的行收集到具有相同订单号的组中,并计算每个组中行的 COUNT 和价格的 SUM。

不能在 GROUP BY 子句中包含 TEXT 、BYTE 、CLOB 或 BLOB 列。要进行分组,必须能够进行排序,并且这些数据类型不存在自然排序顺序。

与 ORDER BY 子句不同,GROUP BY 子句不对数据进行排序。如果想要按特定顺序对数据进行排序,或在投影列表中的聚集上排序,那么在 GROUP BY 子句之后包含 ORDER BY 子句。

下列查询与图 4相同,但包括 ORDER BY 子句以按 price 的升序对检索到的行进行排序,如下所示。

图: 查询

SELECT order_num, COUNT(*) number, SUM (total_price) price
          FROM items
          GROUP BY order_num
          ORDER BY price;

图: 查询结果

  order_num      number         price
              
              1010           2           $84.00
              1011           1           $99.00
              1013           4          $143.80
              1022           3          $232.00
              1001           1          $250.00
              1020           2          $438.00
              1006           5          $448.00
              ⋮
              1002           2         $1200.00
              1004           4         $1416.00
              1014           2         $1440.00
              1019           1         $1499.97
              1021           4         $1614.00
              1007           5         $1696.00

选择特定列一节描述如何在 ORDER BY 子句中使用整数来指示投影列表中列的位置。还可以在 GROUP BY 子句中使用整数来指示列名的位置或在 GROUP BY 列表中显示标号。

以下查询返回与图 6所示相同的行。

图: 查询

SELECT order_num, COUNT(*) number, SUM (total_price) price
          FROM items
          GROUP BY 1
          ORDER BY 3;

构建查询时,Projection 子句的投影列表中的所有非聚集列还必须包含在 GROUP BY 子句中。具有 GROUP BY 子句的 SELECT 语句必须针对每一组返回一行。列出在 GROUP BY 后面的列能够在一组中只反映一个特异值。并且可以返回该值。但是,未列出在 GROUP BY 后面的列可在包含在组中的行中包含不同的值。

下列查询显示如何在连接表的 SELECT 语句中使用 GROUP BY 子句。

图: 查询

SELECT o.order_num, SUM (i.total_price)
          FROM orders o, items i
          WHERE o.order_date > '01/01/98'
          AND o.customer_num = 110
          AND o.order_num = i.order_num
          GROUP BY o.order_num;
该查询连接 ordersitems 表,将表别名指定给它们,并返回以下所示的行。

图: 查询结果

  order_num            (sum)
          
          1008          $940.00
          1015          $450.00