我们经常需要汇总数据而无需实际检索出这些数据,为此SQL提供了专门的函数。使用这些函数,SQL查询能够高效地检索数据,以便进行分析和报表生成。这类检索的例子包括:
- 确定表中行数(或者满足某个条件或包含某个特定值的行数);
- 获得表中某些列的和;
- 找出表列(或所有行或某些特定的行)的最大值、最小值、平均值。
上述例子都需要汇总表中的数据,而无需检索数据本身。因此,返回实际表数据会浪费时间和处理资源。我们真正需要的是汇总信息。
为方便这种类型的检索,SQL提供了五个聚集函数,这些函数能够执行上述检索任务。SQL的聚集函数在各种主要的SQL实现中得到了广泛且一致的支持。
1.AVG()函数
AVG()函数通过计算表中指定列值的总和,并除以行数,来求得该列的平均值。AVG()可用于返回所有列的平均值,也可用于返回特定列或行的平均值。以下示例使用AVG()返回Products表中所有产品的平均价格:
SELECT AVG(prod_price) AS avg_price
FROM Products;
分析:此SELECT语句返回值avg_price,它表示Products表中所有产品的平均价格。
AVG()也可用于确定特定列或行的平均值。以下示例返回特定供应商所提供产品的平均价格:
SELECT AVG(prod_price) AS avg_price
FROM Products
WHERE vend_id = 'DLL01';
分析:这条SELECT语句与前一条的不同之处在于,它包含了WHERE子句,用于过滤出vend_id为'DLL01'的产品,因此avg_price中返回的值只是该供应商产品的平均值。
说明:AVG()函数会忽略列值为NULL的行。
2.COUNT()函数
COUNT()函数用于计数。可以使用COUNT()确定表中行的数目或符合特定条件的行的数目。
COUNT()函数有两种使用方式:
- 使用COUNT(*)对表中所有行进行计数,无论列中是否包含空值(NULL)。
- 使用COUNT(column)对特定列中具有非空值的行进行计数,忽略NULL值。
以下示例返回Customers表中顾客的总数:
SELECT COUNT(*) AS num_cust
FROM Customers;
分析:在此示例中,利用COUNT(*)对所有行进行计数,无论行中各列的值是什么。计数结果在num_cust中返回。
以下示例只对具有电子邮件地址的客户进行计数:
SELECT COUNT(cust_email) AS num_cust
FROM Customers;
分析:这条SELECT语句使用COUNT(cust_email)对cust_email列中有值的行进行计数。在此示例中,假设cust_email的计数为3(表示5个顾客中只有3个顾客有电子邮件地址)。
3.MAX()函数
MAX()函数返回指定列中的最大值。MAX()要求指定列名,如下所示:
SELECT MAX(prod_price) AS max_price
FROM Products;
分析:这里,MAX()返回Products表中最贵物品的价格。
提示:对非数值数据使用MAX()
虽然MAX()一般用来找出最大的数值或日期值,但许多(并非所有)DBMS允许将它用来返回任意列中的最大值,包括返回文本列中的最大值。在用于文本数据时,MAX()返回按该列排序后的最后一行。
说明:MAX()函数会忽略列值为NULL的行。
4.MIN()函数
MIN()函数的功能与MAX()函数相反,它返回指定列的最小值。与MAX()一样,MIN()要求指定列名,如下所示:
SELECT MIN(prod_price) AS min_price
FROM Products;
分析:其中MIN()返回Products表中最便宜物品的价格。
提示:对非数值数据使用MIN()
虽然MIN()一般用来找出最小的数值或日期值,但许多(并非所有)DBMS允许将它用来返回任意列中的最小值,包括返回文本列中的最小值。在用于文本数据时,MIN()返回该列排序后最前面的行。
说明:MIN()函数会忽略列值为NULL的行。
5.SUM()函数
SUM()函数用来返回指定列值的总和(总计)。
以下示例中,OrderItems表包含订单中实际的物品,每个物品有相应的数量。可以如下检索所订购物品的总数(所有quantity值之和):
SELECT SUM(quantity) AS items_ordered
FROM OrderItems
WHERE order_num = 20005;
分析:函数SUM(quantity)返回订单中所有物品数量之和,WHERE子句确保只统计某个特定订单中的物品。
SUM()也可以用来合计计算值。以下示例中,合计每项物品的item_price*quantity,得出总的订单金额:
SELECT SUM(item_price*quantity) AS total_price
FROM OrderItems
WHERE order_num = 20005;
分析:函数SUM(item_price*quantity)返回订单中所有物品价格之和,WHERE子句同样确保只统计某个特定订单中的物品。
说明:SUM()函数会忽略列值为NULL的行。
6.聚集不同值
以上五个聚集函数都可以如下使用:
- 对所有行执行计算,不指定参数或使用ALL参数(因为ALL是默认行为)。
- 只包含不同的值,指定DISTINCT参数。
提示:ALL为默认行为,因此不需要显式指定。如果不指定DISTINCT,则假定为ALL。
以下示例使用AVG()函数返回特定供应商提供的产品的平均价格。它与上面的SELECT语句相同,但使用了DISTINCT参数,因此平均值只考虑各个不同的价格:
SELECT AVG(DISTINCT prod_price) AS avg_price
FROM Products
WHERE vend_id = 'DLL01';
分析:在使用了DISTINCT后,此示例中的avg_price可能会更高,因为有多个物品具有相同的较低价格。排除这些重复的价格后,平均价格会相应提升。
注意:DISTINCT 不能用于COUNT(*)
如果指定列名,则 DISTINCT 只能用于 COUNT()。DISTINCT 不能用于COUNT(*)。类似地,DISTINCT 必须使用列名,不能用于计算或表达式。
提示:将DISTINCT 用于MIN()和MAX()
虽然 DISTINCT 从技术上可用于 MIN()和 MAX(),但这样做实际上没有价值。一个列中的最小值和最大值不管是否只考虑不同值,结果都是相同的。
7.组合聚集函数
到目前为止的所有聚集函数示例都只涉及单个函数。但实际上,SELECT语句可以根据需要包含多个聚集函数。以下示例展示了如何组合使用多个聚集函数:
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;
分析:这里用单条SELECT语句执行了四个聚集计算,返回了四个值(Products表中物品的数目、产品价格的最高值、最低值以及平均值)。
总结:
聚集函数用于汇总数据。SQL支持五个聚集函数,这些函数可以以多种方式使用,返回所需的结果。这些函数非常高效,它们返回的结果通常比在自己的客户端应用程序中计算要快得多。