跳转到主要内容
模块 3 · 第 3 课(共 4)课程中的11/57~10 min
模块课程(3/4)

使用 GROUP BY 进行分组

在模块 2 中,您了解到 COUNT(*)、AVG(...)、SUM(...) 减少了所有 行到单个结果行。但如果你想要平均工资怎么办? 针对每个部门,而不是针对整个公司?你想要一行per 组。这是 GROUP BY 的工作。

语法

SQL
SELECT grouping_column, AGGREGATE_FUNCTION(...)
FROM   table
GROUP BY grouping_column;

用英语阅读:“将行分成具有相同值的组 grouping_column,并为每个组计算聚合“。

SQL
-- Average salary per department:
SELECT department_id, AVG(salary) AS average
FROM   employees
GROUP BY department_id;

结果对于在中找到的每个不同的 department_id** 有一行 employees。您将获得 5 行:4 个部门各一行(1、2、 3、4) 加上一个 NULL (Andrea Costa)。

使用 JOIN 获得可读的名称

通常您希望按 department_id 进行分组,但显示该对象的名称 部门。您可以将 GROUP BY 与 JOIN 结合起来:

SQL
SELECT d.name AS department,
       COUNT(*)    AS count,
       AVG(e.salary) AS average_salary
FROM   employees   AS e
JOIN   departments AS d ON e.department_id = d.id
GROUP BY d.name
ORDER BY count DESC;

这是一个成熟的商业智能查询:三行 告诉您每个部门有多少员工以及他们的收入 平均值,从大到小排序。

黄金法则

当您使用 GROUP BY 时,SELECT 中的每一列都必须是:

  1. 分组列之一(例如 department_id、d.name),或
  2. 在聚合函数内部(例如 AVG(salary)、COUNT(*))。
SQL
-- ERROR: first_name is neither in GROUP BY nor inside an aggregate
SELECT department_id, first_name, AVG(salary)
FROM   employees
GROUP BY department_id;

PostgreSQL 返回显式错误(“列必须出现在 GROUP BY 中) 子句或在聚合函数中使用“)。这是常见的前几周 错误:如果你看到它,停下来问问自己*“它的价值是什么 first_name 对于 3 人一组?"* — 没有单一的答案,并且 这就是引擎拒绝的原因。

尝试一下

锻炼#sql.m3.l3.e1
尝试:0加载中...

对于每个部门,计算其包含多少员工。返回两列:部门名称 (departments.name) 和员工人数。每个部门一行。

正在加载编辑器...
显示提示

使用 COUNT(*) 进行聚合并按 d.name 进行分组。 SELECT 必须仅包含分组列和聚合。

3 次尝试后可用的解决方案

复习练习

锻炼#sql.m3.l3.e2
尝试:0加载中...

对于每个部门 (departments.name),计算其员工的平均工资 (AVG(salary)),从最高到最低排序。

正在加载编辑器...
显示提示

AVG(e.salary) 作为总计,GROUP BY d.name,ORDER BY 平均 DESC。

3 次尝试后可用的解决方案