CodeGym /课程 /SQL SELF /NULL 对聚合函数的影响:SUM(), COUNT(), AVG(), MIN(), MAX()

NULL 对聚合函数的影响:SUM(), COUNT(), AVG(), MIN(), MAX()

SQL SELF
第 9 级, 课程 2
可用

回忆一下,聚合函数就是那种能一次性处理多行数据并返回一个结果的函数。在 PostgreSQL 里你经常会用到这些聚合函数:

  • SUM() — 求和。
  • AVG() — 求平均值。
  • MIN() — 找最小值。
  • MAX() — 找最大值。
  • COUNT() — 统计行数。

乍一看很简单:把列或者表达式丢进函数里,直接拿结果。但如果列里有 NULL 呢?

NULL 在聚合函数里的表现:快速了解

这时候就有意思了:

  • SUM() 和 AVG() 会忽略 NULL。只要有一条记录是 NULL,它就不会参与计算。挺合理的,毕竟如果有人“没来参加聚会”,总和怎么会变?平均值也一样,缺一个数怎么算?
  • MIN() 和 MAX() 也会跳过 NULL。它们只会在不是 NULL 的数据里找最小或最大。所以你找最年轻的员工时,如果有人没填生日,NULL 不会被选中。
  • COUNT(*) 会统计所有行,包括有 NULL 的。而 COUNT(column) 只会统计指定列有值的行,也就是 NULL 会被忽略。

我们来用例子看看。

聚合函数和 NULL 的用法例子

这是 students_scores 表,存着学生的测试分数:

student_id name score
1 阿丽萨 85
2 鲍勃 NULL
3 查理 92
4 达娜 NULL
5 叶莲娜 74

现在我们写几个查询,看看结果:

  1. 所有分数的总和:SUM()
SELECT SUM(score) AS total_score
FROM students_scores;

结果:

total_score
251

你看,缺失的 NULL 分数根本没参与求和。阿丽萨 (85)、查理 (92)、叶莲娜 (74) 的分数加起来就是 251。鲍勃和达娜就被跳过了。

  1. 平均分:AVG()
SELECT AVG(score) AS average_score
FROM students_scores;

结果:

average_score
83.67

同样,NULL 被无视了,平均值只算有分数的:(85 + 92 + 74) / 3 = 83.67。

  1. 最小分和最高分:MIN() 和 MAX()
SELECT
    MIN(score) AS min_score, 
    MAX(score) AS max_score 
FROM students_scores;

结果:

min_score max_score
74 92

这里也一样:NULL 还是被忽略,最小分是 74,最大分是 92。

  1. 统计行数:COUNT(*) vs COUNT(column)
SELECT
    COUNT(*) AS total_rows, 
    COUNT(score) AS non_null_scores 
FROM students_scores;

结果:

total_rows non_null_scores
5 3
  • COUNT(*) 统计了所有行,包括 score 是 NULL 的。
  • COUNT(score) 只算 score 有值的行。

实用案例

来几个实际点的例子。

例子 1:统计有工资和没工资的员工数量

假设我们有个 employees 表,里面有工资。

id name salary
1 Alex Lin 50000
2 Maria Chi NULL
3 Anna Song 60000
4 Otto Art NULL
5 Liam Park 55000

我们想知道有多少员工填了工资,有多少没填。

SELECT
    COUNT(*) AS total_employees,
    COUNT(salary) AS employees_with_salary,
    COUNT(*) - COUNT(salary) AS employees_without_salary
FROM employees;

这里:

  • COUNT(*) 返回员工总数。
  • COUNT(salary) 统计填了工资的员工数。
  • 没填工资的数量就是两者相减。

结果

total_employees employees_with_salary employees_without_salary
5 3 2

例子 2:计算商品平均价格,考虑缺失数据

你是魔法商店老板,products 表里有 price 列,但有些商品还没定价。

id name price
1 Magic Wand 150
2 Enchanted Cloak NULL
3 Potion Bottle 75
4 Spell Book 200
5 Crystal Ball NULL

你只想算有价格的商品的平均价。

SELECT AVG(price) AS average_price
FROM products;

结果:

average_price
141.6667

如果你想给没定价的商品设个默认价(比如 0),可以用 COALESCE(),这个我们下节课讲。

例子 3:找出学生的最小和最大年龄

students 表里有学生年龄,但有些学生年龄未知(NULL)。

id name age
1 Alex Lin 20
2 Maria Chi NULL
3 Anna Song 19
4 Otto Art 22
5 Liam Park NULL

我们想知道最小和最大的学生年龄。

SELECT
    MIN(age) AS youngest_student,
    MAX(age) AS eldest_student
FROM students;

结果:

youngest_student eldest_student
19 22

这个查询只会返回有年龄的学生的最小和最大年龄。NULL 还是被跳过了。

注意事项和坑点

用聚合函数处理 NULL 时,记住这些:

  • 在 SUM() 和 AVG() 里,NULL 不参与计算。这样你就不会把“空值”算进去。
  • 如果你想统计有 NULL 的行,用 COUNT(*)。
  • 用 MIN() 或 MAX() 时,NULL 不影响结果。但如果整列全是 NULL,结果也是 NULL。

和 NULL 打交道的小贴士

  1. 根据实际需求来。 你得搞清楚你的查询到底要不要考虑 NULL。有时候像 AVG() 这样忽略 NULL 正合适。有时候比如统计总数,NULL 也得算进去。
  2. 需要时用 COALESCE()。 如果你想在计算时把 NULL 换成默认值,COALESCE() 就是你的好帮手(不过这个下节课再说)。
  3. 别搞混 COUNT(*) 和 COUNT(column)。 这是新手最容易犯的错。前者统计所有行,后者只算有值的行。

现在你知道了,NULL 这个“沉默的家伙”会怎么影响聚合函数。掌握了这些,你就能避免踩坑,还能用 NULL 玩出花来。下节课我们会学一个强大的工具 COALESCE(),让你处理 NULL 更溜!

2
任务
SQL SELF, 第 9 级, 课程 2
已锁定
分数总和与平均值
分数总和与平均值
2
任务
SQL SELF, 第 9 级, 课程 2
已锁定
统计有数据和无数据的行数
统计有数据和无数据的行数
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION