CodeGym /课程 /SQL SELF /数据分组(GROUP BY):语法和结构

数据分组(GROUP BY):语法和结构

SQL SELF
第 8 级 , 课程 0
可用

想象一下,你在处理成千上万行数据——怎么在里面找到有用的信息?这时候 GROUP BY 操作符就像 SQL 里的指挥家一样登场了。它把杂乱无章的数据变成一首有节奏的旋律:统计、分组、总结。想知道每个客户下了多少订单、每门课有多少学生、或者各部门工资怎么分布?这些都靠 GROUP BY。今天我们就来聊聊怎么和它做朋友,把你的表用到极致。

分组其实就是把在某一列或几列里值相同的行合并成逻辑上的一组。这样你就能对每组单独用聚合函数了。

比如你有个员工表,想知道每个部门的平均工资。一个部门就是一组。SQL 用 GROUP BY 把员工表按部门分组,然后对每组用 AVG()

GROUP BY 的语法

用 SQL 分组的核心规则:如果你用了 GROUP BY,那所有没用聚合函数的列都必须写在 GROUP BY 里。

语法:

SELECT 列1, 
       聚合函数(列2)
FROM 表
GROUP BY 列1;

操作步骤:

  1. GROUP BY 里写上你想分组的列。
  2. 用聚合函数来计算每组的值。
  3. 所有在 SELECT 里但没用聚合函数的列,都得写在 GROUP BY 里。没写 SQL 会报错,别问为什么,SQL 就是这么严格。

例子:按院系分组学生

假设我们有个 students 表,存着学生的信息:

id name faculty gpa
1 Alex Lin ComputerSci 3.8
2 Maria Chi Math 3.5
3 Anna Song ComputerSci 4.0
4 Otto Art Math 3.9
5 Liam Park Physics 3.7

现在我们想知道每个院系的平均分(GPA)。写个带 GROUP BY 的查询:

SELECT faculty, AVG(gpa) AS avg_gpa
FROM students
GROUP BY faculty;

结果:

faculty avg_gpa
ComputerSci 3.9
Math 3.7
Physics 3.7

SQL 先按 faculty 列把数据分组,然后对每组用 AVG()

GROUP BY 的细节

  1. SELECT 里的列要求

SQL 要求你在 SELECT 里写的所有列,如果没用聚合函数(比如 SUM()COUNT()),都得在 GROUP BY 里出现。因为没分组 SQL 不知道该显示哪个值。

试试下面这个查询,你会报错:

SELECT name, AVG(gpa)
FROM students
GROUP BY faculty;

错误:name 列没写在 GROUP BY 里。要修正,加上 name

SELECT name, AVG(gpa)
FROM students
GROUP BY faculty, name;

但这样分组就到具体学生了——其实不是我们一开始想要的效果。

  1. 多列分组

你可以不只按一列分组,还能多列一起分组。比如除了院系还想按名字分组。直接在 GROUP BY 里加第二个列:

SELECT faculty, name, AVG(gpa) AS avg_gpa
FROM students
GROUP BY faculty, name;

原始表:

id name faculty gpa
1 Alex Lin ComputerSci 3.8
2 Maria Chi Math 3.5
3 Anna Song ComputerSci 4.0
4 Otto Art Math 3.9
5 Liam Park Physics 3.7

结果:

faculty name avg_gpa
ComputerSci Alex Lin 3.8
ComputerSci Anna Song 4.0
Math Maria Chi 3.5
Math Otto Art 3.9
Physics Liam Park 3.7
  1. 用多个聚合函数分组

别只用一个聚合函数!比如我们想统计每个院系有多少学生,还想算平均分:

SELECT faculty,
       COUNT(*) AS student_count, 
       AVG(gpa) AS avg_gpa
FROM students
GROUP BY faculty;

原始表:

id name faculty gpa
1 Alex Lin ComputerSci 3.8
2 Maria Chi Math 3.5
3 Anna Song ComputerSci 4.0
4 Otto Art Math 3.9
5 Liam Park Physics 3.7

结果:

faculty student_count avg_gpa
ComputerSci 2 3.9
Math 2 3.7
Physics 1 3.7

SQL 分组的细节:能选什么,不能选什么

写分组查询很简单,但你会发现一半的查询都跑不起来。分组的逻辑和我们脑子里想的不太一样。

如果你的 SQL 查询里有 GROUP BY,那结果里的所有列都要么是聚合函数算出来的,要么就是 GROUP BY 里分组用的列。

  • 用聚合函数基于组内的列算出来的。
  • 直接来自 GROUP BY——就是用来分组的列。

比如你对学生表做 GROUP BY 查询,结果表里是不会有具体学生的!你能有平均身高、平均体重、平均分。像下面这样写就不行:

SELECT faculty, name
FROM students
GROUP BY faculty;

我们来分析下为啥。

GROUP BY faculty 会把 students 表里的学生按 faculty 分组。每组学生的 faculty 都一样,所以可以说组有 faculty 这个属性。但 name 每个学生都不一样,所以组没有 name 这个属性。

GROUP BY faculty, gender 会把 students 表里的学生按 facultygender 分组。这样每组学生的 facultygender 都一样,所以组有这两个属性。但 name 还是没有。

这样写就没问题:

SELECT faculty, gender
FROM students
GROUP BY faculty, gender;

甚至可以这样:

SELECT
    faculty, 
    gender, 
    AVG(age) as group_avg_age,  -- 这个值是基于组内 age 算出来的
    MAX(high) as group_high     -- 这个值是基于组内 high 算出来的
FROM students
GROUP BY faculty, gender;

但直接在 SELECT 里用 agehigh 是不行的。

GROUP BY 时常见的坑

你开始写 GROUP BY 查询时,这些坑很容易踩:

  1. SELECT 里没写全列。 记住,所有不是聚合的列都得写在 GROUP BY 里。不然 SQL 不知道怎么显示。

  2. NULL 分组。 NULL 会被当成一个单独的组。如果你的列里有 NULL,SQL 会给 NULL 单独分一组。

  3. 分组太细。 如果你不小心在 GROUP BY 里加了太多列,结果会特别细,分析起来很麻烦。

现在你已经知道怎么用 GROUP BY 高效分组数据了。这是 SQL 里最强大的工具之一,让你轻松搞定聚合数据和结构化报表。接下来我们还会继续深入分组的魔法,看看怎么用 HAVING 加更多过滤条件。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION