Skip to content

sql-aggregate-functions

聚合是将多个值汇总为一个值的过程。想象一下从单个考试分数计算班级平均分——这就是聚合。SQL 提供了强大的聚合函数来对多行数据进行计算,这对于分析和报告至关重要。

虽然 SQL 提供了许多聚合函数,但这五个是最常见的,它们构成了数据汇总的基础。在我们的示例中,我们将使用一个 Employees 表:

CREATE TABLE Employees (
ID INT PRIMARY KEY,
Name VARCHAR(100),
Department VARCHAR(50),
Salary DECIMAL(10, 2),
Bonus DECIMAL(10,2)
);
INSERT INTO Employees VALUES
(1, 'Alice', 'Engineering', 90000, 5000),
(2, 'Bob', 'Engineering', 85000, 4000),
(3, 'Charlie', 'Sales', 75000, 10000),
(4, 'David', 'Sales', 78000, 12000),
(5, 'Eve', 'HR', 60000, NULL); -- 注意 Bonus 为 NULL
  • COUNT(): 计数行数。COUNT(*) 计数所有行。COUNT(column) 计数该列中非 NULL 的值。SELECT COUNT(*) FROM Employees; → 5。SELECT COUNT(Bonus) FROM Employees; → 4。
  • SUM(): 计算数字列的总和,忽略 NULL 值。SELECT SUM(Salary) FROM Employees; → 388000。
  • AVG(): 计算数字列的平均值,忽略 NULL 值。SELECT AVG(Salary) FROM Employees; → 77600。
  • MAX(): 返回列中的最大值。SELECT MAX(Salary) FROM Employees; → 90000。
  • MIN(): 返回列中的最小值。SELECT MIN(Salary) FROM Employees; → 60000。

当与 GROUP BY 子句结合使用时,聚合的真正威力才能发挥出来。GROUP BY 用于将相同的数据排列成组,允许你独立地对每个组应用聚合函数。

SELECT
Department,
AVG(Salary) AS AverageSalary,
COUNT(*) AS NumberOfEmployees
FROM
Employees
GROUP BY
Department;

此查询首先按部门对员工进行分组,然后计算每个组的平均薪资和员工数量。

如何根据聚合值过滤结果?你不能使用 WHERE,因为 WHERE 在聚合发生之前过滤行。为此,你需要 HAVING 子句,它在聚合完成之后过滤组。

让我们只查找平均薪资大于 80,000 美元的部门。

SELECT
Department,
AVG(Salary) AS AverageSalary
FROM
Employees
GROUP BY
Department
HAVING
AVG(Salary) > 80000;

这将只返回“Engineering”部门。

一个非常常见的要求是计算列中唯一值的数量。这通过在 COUNT 函数内部添加 DISTINCT 关键字来完成。

-- 有多少个独特的部门?
SELECT COUNT(DISTINCT Department) FROM Employees; -- 结果:3

了解数据库处理查询的逻辑顺序是避免错误的关键。尽管你首先编写 SELECT,但数据库以不同的顺序执行子句:

  1. FROM / JOIN:收集源数据。
  2. WHERE:过滤单个行。
  3. GROUP BY:对过滤后的行进行分组。
  4. HAVING:过滤结果组。
  5. SELECT:选择最终列并执行表达式。
  6. DISTINCT:从结果中删除重复行。
  7. ORDER BY:对最终结果集进行排序。
  8. LIMIT / OFFSET:限制返回的行数。

如果你想对一组行执行计算,但仍返回所有原始行怎么办?例如,显示每个员工的薪资以及他们部门的平均薪资。这就是窗口函数的用武之地。它们是一种现代、强大的功能,可以在与当前行相关的“窗口”行上执行类似聚合的计算,而不会将它们折叠。一个例子是 AVG(Salary) OVER (PARTITION BY Department)。