Last chance! 50% off DataCamp Premium
Sale ends in
如果您从事数据相关工作,那么基于给定数据集构建报告是一项必备技能。归根结底,您希望能够利用手头的数据回答关键的业务问题。很多时候,这些答案会以图表的形式呈现。但有时,也需要以表格形式展示报告。无论哪种情况,您可能都需要通过简单的计算来汇总数据。在 SQL 中,您可以使用聚合函数来汇总/聚合数据。借助这些函数,您可以回答如下问题:
some_column_from_the_table 的最大值是多少?或者another_column_from_the_table,some_column_from_the_table 的最小值是多少?以及更多类似问题。
让我们开始进行一些数据聚合。
注意:要跟上本教程,您需要了解如何在 PostgreSQL(本教程所用的关系型数据库管理系统)中编写基础查询。这篇教程可以作为很好的复习材料。
首先,建立一个 PostgreSQL 数据库,并恢复包含本教程所用数据表的这个备份。如果您想学习如何在 PostgreSQL 中恢复数据库备份,可以参考这篇教程的第一部分。
如果您成功恢复了备份,应该能在数据库中看到名为 international_debt 的表(如果还没有数据库,需要先创建一个)。我们先快速查看一下该表的前几行(一个简单的 select 查询即可完成):

该表包含了本年度全球不同国家在不同类别(参见 indicator_name 和 indicator_code 列)的债务统计信息。debt 列展示了某一国家在特定类别中的债务金额(美元)。这些数据属于经济学领域,常用于分析不同国家的经济状况。数据来自世界银行。
现在您已经成功设置了数据库,让我们运行一些简单查询来进一步了解数据。打开 pgAdmin 工具,开始吧。
从上图可以看到,对于同一国家,在不同类别下存在许多重复条目。由此很快会引出一个问题:
该表包含哪些不同的国家记录?
如果您仅对 country_name 列执行 select 查询,是无法得到正确答案的,因为查询结果会包含重复值。我们使用 DISTINCT 关键字来解决这个问题。
select distinct country_name from international_debt;
这将返回类似如下结果:

现在,您对上述问题就有了合理的答案。在进入聚合函数之前,再来一个问题:
表中有多少种不同的债务指标?
回答该问题的查询应与上面的类似,只需更换列名。把它当作一个小练习吧。结果应与下图相似:

我们从运行一个带有聚合函数的查询开始,并据此逐步展开。在此过程中,您会了解在 SQL 中应用聚合函数时需要遵循的语法和结构。
select sum(debt) from international_debt;
结果如下:

使用 SUM() 聚合函数,您可以计算某一列(包含数值)的算术总和。通过上述查询,您得知了该表所列国家的债务总额。
注意,SUM() 在计算总和时不会考虑 NULL 值。现在,让我们回答这个问题:
最大的债务金额是多少?
这时就该用到 MAX() 聚合函数了:
select max(debt) from international_debt;
答案是:

与 SUM() 一样,MAX() 在计算时也不考虑 NULL 条目。同理还有 MIN() 函数。请在评论区告诉我 debt 列的最小值?现在,最好检查一下 debt 列中是否存在无效条目,以确保目前为止的结果是正确的。
注意,如上所示,您可以用小写来书写这些函数。
当您执行此查询:select * from international_debt where debt is null;,应该会得到空结果。现在我们来找出表中不同国家的总数。
select count(distinct(country_name)) from international_debt;
可以看到,表中一共有 124 个不同的国家。请留意上述查询中函数的嵌套顺序。是的,这里是允许的,也就是可以以逻辑方式串联多个聚合函数。
现在,假设您想查看 debt 列的平均值。函数是 AVG():
select avg(debt) from international_debt;
您会看到该值为 1306633214.966397971(美元)。为这些结果提供合适的列名是个好主意。从上面的结果可以看到,PostgreSQL 在返回结果时会将列名更改为查询中包含的聚合函数名。因此,最好为这些列指定一个合适的别名。您可以这样做:
select avg(debt) as Average_Debt_By_A_Country from international_debt;
结果更易于理解:

现在我们把它提升到稍微复杂一点的层面。要能够回答类似 相对于 another_column_from_the_table,some_column_from_the_table 的最小值是多少? 这样的问题,您需要将聚合函数与 GROUP BY 子句配合使用。让我们看看如何操作。
假设您要生成一份报告,展示 country_name 以及其债务总和。示例如下:

这样的报告在现实世界中相当常见。那么,得到这样的报告需要什么查询?您需要对 debt 使用 SUM() 函数。同时,还需要与债务总额一起展示 country_name。让我们执行以下查询:
select country_name, sum(debt) from international_debt;
这是否会产生如下错误?
ERROR: column "international_debt.country_name" must appear in the GROUP BY clause or be used in an aggregate function
我们来理解一下这意味着什么。当您将一个聚合函数(如 SUM())与一个未聚合的列(如 country_name)一起使用时,需要将该未聚合列放入 GROUP BY 子句中。因此,正确的查询是:
select country_name, sum(debt) as total_debt from international_debt group by country_name;
结果就正确了:

注意查询中对列名的别名处理。
现在,假设您需要按 total_debt 降序对该报告进行排序。还记得 ORDER BY 子句吗?是的,您也可以将聚合函数与 ORDER BY 子句配合使用:
select country_name, sum(debt) as total_debt from international_debt
group by country_name order by total_debt desc;
结果现在应为逆序排序:

注意您在 ORDER BY 子句中使用的列。
接下来另一个重要问题:
不同类别中的最高债务金额是多少(按逆序排序)?
这里需要使用 MAX() 函数。要回答这个问题,现在写出查询应该不难了。
select indicator_code, max(debt) as maximum_debt from international_debt
group by indicator_code order by maximum_debt desc;
您会得到一份简洁的报告:

这类报告也可以限制返回的行数。比如,您只想在上述报告中展示前五条记录。可以使用 LIMIT 子句实现。
select indicator_code, max(debt) as maximum_debt from international_debt
group by indicator_code order by maximum_debt desc
limit 5;
到了本教程的最后一份报告。您需要在上述报告中加入国家名称。如何实现?可以使用以下查询:
select country_name, indicator_code, max(debt) as maximum_debt from international_debt
group by country_name, indicator_code order by maximum_debt desc;
又一份不错的报告:

在上述查询中,您在 SELECT 子句后加入了 country_name 列,并在 GROUP BY 中也加入了它。您可以将这种模式扩展到任意数量的列。
在生成此类报告时,GROUP BY、ORDER BY 和 LIMIT 的先后顺序非常重要。如果不小心改变了顺序,就会遇到错误。请亲自试试:
select country_name, sum(debt) as total_debt from international_debt
order by total_debt desc group by country_name;
结果如下:
ERROR: syntax error at or near "group"
LINE 1: ... from international_debt order by total_debt desc group by c...
在上述查询中,您将 ORDER BY 子句置于 GROUP BY 之前,这是不允许的。事实上,即便不使用聚合函数,这样的顺序也是不适用的。正确的顺序是:GROUP BY -> ORDER BY -> LIMIT。务必牢记。
恭喜您!您已经学完了本教程。在本教程中,您了解了 PostgreSQL 中不同的聚合函数,以及如何使用它们来生成有用的报告。对于数据科学家而言,这些确实是关键技能。若想系统性提升 SQL 技能,您可以学习以下 DataCamp 课程:
SQL 课程
课程