🙏 感谢您的支持! 我们在七月份已经筹集了 $65 — 这足够我们工作到下个月。请帮助我们保持进度,进一步支持这个项目。 支持这个项目 →
SQL 代码已复制到剪贴板

课程 4.1 · 阅读时间:约 8 分钟

SQL 聚合函数帮助将行集转换为摘要指标:计数、求和、平均值、最小值和最大值。在本课中,您将通过 Sakila 示例学习最常见的聚合,并了解如何为每个任务选择正确的计数方法。到课程结束时,您将能够自信地在分析 SQL 中使用 COUNTSUMAVGMINMAX

SQL 中的基本聚合函数

在之前的课程中,您专注于选择单个行。现在我们进入下一个重要步骤:从数据中计算摘要值。

聚合函数在报告和分析中至关重要,因为它们可以快速回答“有多少?”、“总共多少?”和“平均值是多少?”等问题。

核心聚合函数

COUNT() - 计数行

基本语法:

COUNT(expression)

示例:

SELECT COUNT(*) AS total_payments
FROM payment;

结果:查询返回 payment 表中的行总数。

COUNT(column) 与 COUNT(*)

这两种形式看起来相似,但行为不同:

  • COUNT(*) 计算结果集中的所有行。
  • COUNT(column) 仅计算 column 不为 NULL 的行。

如果某列包含 NULL,则 COUNT(column) 可能小于 COUNT(*)

SELECT
    COUNT(*) AS total_rentals,
    COUNT(return_date) AS returned_rentals
FROM rental;

解释:total_rentals 计算所有租赁,而 returned_rentals 仅计算 return_date 被填充的行。

COUNT(DISTINCT ...) - 计数唯一值

当您需要唯一值的数量,而不仅仅是行数时,使用 COUNT(DISTINCT column)

SELECT COUNT(DISTINCT customer_id) AS unique_customers
FROM payment;

结果:查询返回进行了支付的唯一客户数量,即使一个客户有多行支付记录。

在实践中,这对于“有多少不同的客户购买”这样的问题很重要,因为普通的 COUNT(*) 会因为重复行而过度计数。

SUM() - 计算总和

SELECT SUM(amount) AS total_amount
FROM payment;

结果:返回 amount 列的总和。

SUM(amount) 忽略 NULL。如果所有值都是 NULL,结果为 NULL

AVG() - 计算平均值

SELECT AVG(amount) AS average_amount
FROM payment;

结果:返回非 NULL 行的平均值。

如果您希望包含 NULL 的行影响分母,请使用以下方法之一:

SELECT
    AVG(amount) AS avg_ignore_null,
    AVG(COALESCE(amount, 0)) AS avg_include_null_as_zero,
    SUM(amount) / COUNT(*) AS avg_sum_div_all_rows
FROM payment;

MAX() - 查找最大值

SELECT MAX(amount) AS max_amount
FROM payment;

结果:返回 amount 中的最大值。

MIN() - 查找最小值

SELECT MIN(amount) AS min_amount
FROM payment;

结果:返回 amount 中的最小值。

MIN()MAX() 都会忽略 NULL。如果所有值都是 NULL,它们会返回 NULL

MIN(column) 与 ORDER BY ... LIMIT 1

它们并不总是等价的。

SELECT MIN(column_name)
FROM table_name;

SELECT column_name
FROM table_name
ORDER BY column_name
LIMIT 1;
  • MIN(column_name) 查找非 NULL 值中的最小值。
  • ORDER BY ... LIMIT 1 返回排序后的第一行。
  • 如果您的 DBMS 将 NULL 排在前面,则第二个查询可能返回 NULL,而 MIN() 仍然返回最小的非 NULL 值。

MIN() 的可靠等价物:

SELECT column_name
FROM table_name
WHERE column_name IS NOT NULL
ORDER BY column_name
LIMIT 1;

实际用法

计数客户

SELECT COUNT(*) AS total_customers
FROM customer;

按员工计算总销售额

SELECT
    staff_id,
    SUM(amount) AS staff_total
FROM payment
GROUP BY staff_id;

按客户计算平均支付

SELECT
    customer_id,
    AVG(amount) AS avg_payment
FROM payment
GROUP BY customer_id;

计数唯一支付客户

SELECT COUNT(DISTINCT customer_id) AS paying_customers
FROM payment;

常见问题解答

COUNT(*) 和 COUNT(column) 之间有什么区别?

COUNT(*) 计算所有结果行。COUNT(column) 仅计算指定列不为 NULL 的行。

何时应使用 COUNT(DISTINCT ...)?

当您需要唯一值的数量而不是总行数时使用,例如唯一客户而不是总支付。

为什么 AVG 可能返回意外值?

因为 AVG(column) 忽略 NULL。如果您希望这些行影响分母,请使用 COALESCE 或将 SUM(column) 除以 COUNT(*)


面试问题

SQL 中的聚合函数是什么?

它们是计算多行摘要的函数,例如计数(COUNT)、求和(SUM)或平均值(AVG)。它们每组或整个结果集返回一个值。

COUNT(*)、COUNT(column) 和 COUNT(DISTINCT column) 之间有什么区别?

COUNT(*) 计算所有行,COUNT(column) 计算该列中的非 NULL 值,COUNT(DISTINCT column) 计算唯一的非 NULL 值。

MIN 和 ORDER BY ... LIMIT 1 如何返回不同的结果?

如果某列包含 NULL 且 DBMS 将 NULL 排在前面,ORDER BY ... LIMIT 1 可能返回 NULL,而 MIN() 返回最小的非 NULL 值。


本课的关键要点:

  • 聚合函数快速提供摘要指标。
  • COUNT(*)COUNT(column)COUNT(DISTINCT ...) 解决不同的计数任务。
  • SUMAVGMINMAX 通常忽略 NULL,这会影响分析。
  • 当您需要唯一实体而不是行总数时,COUNT(DISTINCT ...) 是必不可少的。
  • 正确处理 NULL 直接影响报告的准确性。

在下一课中,我们将学习 GROUP BY 并了解如何按类别构建聚合。

尝试解决以下任务,以巩固您在本课中学到的内容。

  1. 最小和最大替换成本
  2. 计算包含演员的电影数量
  3. 电影时长的最小值、最大值和平均值
  4. 按类别计算电影平均时长
  5. 最多样化的演员