MySQL – 不包含在 Group By 中的列选择
在使用 MySQL 中的 GROUP BY 子句进行分组时,如果 SELECT 中有不包含在 GROUP BY 子句中的列,那么会发生什么呢?这是一个很常见的问题,下面我们来一一解答。
阅读更多:MySQL 教程
问题描述
假设我们有一张名为 student 的表格,存储了每个学生的姓名(name)、班级(class)、成绩(score):
| name | class | score |
|---|---|---|
| Alice | A | 85 |
| Bob | A | 90 |
| Carol | A | 95 |
| Dave | B | 80 |
| Eve | B | 75 |
现在我们需要按班级分组,然后计算每个班级的平均成绩,表示为 AVG(score),同时也想查看这个班级中的人数,表示为 COUNT(*)。
所以我们可能会这样写 SQL 语句:
SELECT class, AVG(score), COUNT(*)
FROM student
GROUP BY class;
问题解答
上述 SQL 语句的输出结果是:
| class | AVG(score) | COUNT(*) |
|---|---|---|
| A | 90 | 3 |
| B | 77.5 | 2 |
这一切似乎都很好,但是我们有时可能会想要在 SELECT 中选择除 class、AVG(score)、COUNT(*) 以外的其他列,比如姓名。如果这样写:
SELECT name, class, AVG(score), COUNT(*)
FROM student
GROUP BY class;
那么我们会收到一个错误消息:
1055 – Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column ‘test.student.name’ which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
咋办呢?我们可以在这个 SQL 语句中添加一个函数,让它返回 name 中的一个值。比如 MIN(name) 或 MAX(name)(因为 name 列中的值都是一样的)。
SELECT MAX(name) as name, class, AVG(score), COUNT(*)
FROM student
GROUP BY class;
这样就不会报错了。
总结
在使用 MySQL 的 GROUP BY 子句进行分组时,一定要注意 SELECT 中的列是否包含在 GROUP BY 中,在使用非聚合函数或表达式时一定要使用聚合函数进行代替。
极客教程