汇总数据

本章介绍什么是SQL的聚集函数以及如何利用它们汇总表的数据。

聚集函数

我们经常需要汇总数据而不用把它们实际检索出来,为此MySQL提供了专门的函数。通过这些函数,MySQL查询可用于检索数据,以便分析和报表生成。

常见类型:

  • 确定表中行数(或满足某个条件或包含某个特定值的行数)。
  • 获得表中行组的和。
  • 找出表列(或所有行或某些特定的行)的最大值、最小值和平均值。

这些都是对表中数据(而不是实际数据本身)汇总。故,返回实际数据是对时间和处理资源的一种浪费。

MySQL给出了5个聚集函数:

函数

说明

AVG()

返回某列的平均值

COUNT()

返回某列的行数

MAX()

返回某列的最大值

MIN()

返回某列的最小值

SUM()

返回某列之和

  • 聚集函数(aggregate function) 运行在行组上,计算和返回单个值的函数。
  • 标准偏差 MySQL还支持一系列的标准偏差聚集函数。

AVG()函数

AVG()通过对表中行数计数并计算特定列值之和,求得该列的平均值。

返回products表中所有产品的平均价格:

mysql> SELECT AVG(prod_price) AS avg_price
    -> FROM products;
+-----------+
| avg_price |
+-----------+
| 16.133571 |
+-----------+
1 row in set (0.02 sec)

此SELECT语句返回值avg_price,它包含products表中所有产品的平均价格。avg_price是一个别名(MySQL必知必会——第十章创建计算字段)。

AVG()也可以用来确定特定列或行的平均值:

mysql> SELECT AVG(prod_price) AS avg_price
    -> FROM products
    -> WHERE vend_id = 1003;
+-----------+
| avg_price |
+-----------+
| 13.212857 |
+-----------+
1 row in set (0.01 sec)

此SELECT语句包含了WHERE子句,仅过滤出vend_id为1003的产品,所以avg_price仅返回供应商1003的产品的平均值。

  • 只用于单个列 AVG()只能确定特定数值列的平均值,且列名必须作为参数。
  • NULL值 AVG()函数忽略列值为NULL的行。

COUNT()函数

COUNT()函数进行计数。可用COUNT()确定表中行的数目或符合特定条件的行的数目。

使用COUNT()函数的两种方式:

  1. 使用COUNT(*)对表中行的数目进行计数,包含NULL值列。
  2. 使用COUNT(column)对特定列中具有值的行就行计数,忽略NULL值。

返回customers表中客户的总数:

mysql> SELECT COUNT(*) AS num_cust
    -> FROM customers;
+----------+
| num_cust |
+----------+
|        5 |
+----------+
1 row in set (0.01 sec)

此语句利用COUNT(*)对所有行计数。

对具有邮件地址的客户计数:

mysql> SELECT COUNT(cust_email) AS num_cust
    -> FROM customers;
+----------+
| num_cust |
+----------+
|        3 |
+----------+
1 row in set (0.00 sec)

这条SELECT语句使用COUNT(cust_email)对cust_email列中有值的行进行计数。

  • NULL值 如果指定列名,则指定列的值为NULL的行将被忽略,但如果函数用*号,则不忽略。

MAX()函数

MAX()返回指定列中的最大值。MAX()要求指定列名。

返回products表中最贵的物品价格:

mysql> SELECT MAX(prod_price) AS max_price
    -> FROM products;
+-----------+
| max_price |
+-----------+
|     55.00 |
+-----------+
1 row in set (0.00 sec)
  • 对非数值数据使用MAX() MAX()一般用来找出最大的数值或日期值,但MySQL允许将它用来返回任意列中的最大值,包括返回文本列中的最大值。用于文本数据时,返回最后一行。
  • NULL值 MAX()函数忽略列值为NULL的行。

MIN()函数

MIN()返回指定列的最小值。MIN()要求指定列名。

返回products表中最便宜的物品价格:

mysql> SELECT MIN(prod_price) AS min_price
    -> FROM products;
+-----------+
| min_price |
+-----------+
|      2.50 |
+-----------+
1 row in set (0.00 sec)
  • 对非数值数据使用MAX() MIN()与MAX()类似,MySQL允许将它用来返回任意列中的最小值,包括返回文本列中的最小值。用于文本数据时,返回最前面一行。
  • NULL值 MIN()函数忽略列值为NULL的行。

SUM()函数

SUM()返回指定列值的和(总计)。

检索订单号20005所订购物品的总数(所有quantity值之和):

mysql> SELECT SUM(quantity) AS items_ordered
    -> FROM orderitems
    -> WHERE order_num = 20005;
+---------------+
| items_ordered |
+---------------+
|            19 |
+---------------+
1 row in set (0.00 sec)

SUM()也可以合计计算值,计算总订单金额(item_price*quantity):

mysql> SELECT SUM(item_price*quantity) AS total_price
    -> FROM orderitems
    -> WHERE order_num = 20005;
+-------------+
| total_price |
+-------------+
|      149.87 |
+-------------+
1 row in set (0.00 sec)
  • 在多个列上进行计算 利用标准的算术操作符,所有聚集函数都可用来执行多个列上的计算。
  • NULL值 SUM()函数忽略列值为NULL的行。

聚集不同值

以上聚集函数都可以如下使用:

  • 对所有行执行计算,指定ALL参数或不给参数(ALL为默认)。
  • 只包含不同的值,指定DISTINCT参数。

使用DISTINCT参数检索特定供应商提供的产品的平均价格:

mysql> SELECT AVG(DISTINCT prod_price) AS avg_price
    -> FROM products
    -> WHERE vend_id = 1003;
+-----------+
| avg_price |
+-----------+
| 15.998000 |
+-----------+
1 row in set (0.00 sec)

使用DISTINCT后,avg_price比第一个例子更高,因为多个物品具有相同的价格,排除它们提升了平均价格。

  • ALL为默认 ALL参数不需要指定,因为它是默认行为。
  • 注意 DISTINCT不能用于COUNT(*),否则会产生错误。即,DISTINCT必须使用列名,不能用于计算或表达式。
  • 将DISTINCT用于MIN()和MAX() 虽然DISTINCT可以用于MIN()和MAX(),但没有价值,最大最小值只有一个。

组合聚集函数

SELECT语句可根据需要包含多个聚集函数:

mysql> SELECT COUNT(*) AS num_items,
              MIN(prod_price) AS price_min,
              MAX(prod_price) AS price_max, 
              AVG(prod_price) AS price_avg
    -> FROM products;
+-----------+-----------+-----------+-----------+
| num_items | price_min | price_max | price_avg |
+-----------+-----------+-----------+-----------+
|        14 |      2.50 |     55.00 | 16.133571 |
+-----------+-----------+-----------+-----------+
1 row in set (0.00 sec)

这里用单条SELECT语句执行4个聚集计算。

  • 取别名 在指定别名以包含某个聚集函数的结果时,不应该使用表中实际的列名。唯一的名字使你的代码更易于理解和使用。