原文地址,优先更新https://hhe0.github.io

group by 是一个我们在日常工作学习过程中经常遇到的一个Mysql关键字。现总结其用法如下,内容会不断补充,出现错误欢迎批评指正。

我们先准备一张表和一些记录

我们首先创建学生的成绩表courses:

CREATE TABLE `courses` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增id',
`student` VARCHAR(255) DEFAULT NULL COMMENT '学生',
`class` VARCHAR(255) DEFAULT NULL COMMENT '课程',
`score` INT(255) DEFAULT NULL COMMENT '分数',
PRIMARY KEY (`id`),
UNIQUE KEY `course` (`student`, `class`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

该表记录了学生某节课的考试分数。

courses表中插入记录:

INSERT INTO `courses`(`student`, `class`, `score`) VALUES('A', 'Math', 90);
INSERT INTO `courses`(`student`, `class`, `score`) VALUES('A', 'Chinese', 80);
INSERT INTO `courses`(`student`, `class`, `score`) VALUES('A', 'English', 70);
INSERT INTO `courses`(`student`, `class`, `score`) VALUES('A', 'History', 80); INSERT INTO `courses`(`student`, `class`, `score`) VALUES('B', 'Math', 73);
INSERT INTO `courses`(`student`, `class`, `score`) VALUES('B', 'Chinese', 60);
INSERT INTO `courses`(`student`, `class`, `score`) VALUES('B', 'English', 70);
INSERT INTO `courses`(`student`, `class`, `score`) VALUES('B', 'History', 90); INSERT INTO `courses`(`student`, `class`, `score`) VALUES('C', 'Math', 70);
INSERT INTO `courses`(`student`, `class`, `score`) VALUES('C', 'Chinese', 50);
INSERT INTO `courses`(`student`, `class`, `score`) VALUES('C', 'English', 20);
INSERT INTO `courses`(`student`, `class`, `score`) VALUES('C', 'History', 10); INSERT INTO `courses`(`student`, `class`, `score`) VALUES('D', 'Math', 53);
INSERT INTO `courses`(`student`, `class`, `score`) VALUES('D', 'Chinese', 32);
INSERT INTO `courses`(`student`, `class`, `score`) VALUES('D', 'English', 99);
INSERT INTO `courses`(`student`, `class`, `score`) VALUES('D', 'History', 100);

Group By有什么用

我们使用几个简单的例子看一下group by的作用:

SELECT * FROM `courses` GROUP BY `class`;

执行的结果是:

![企业微信截图_20180820143057.png-7.3kB][1]
类似地,我们按照`score`对记录进行分组:
```sql
SELECT * FROM `courses` GROUP BY `score`;
```
执行的结果是:
![ScreenClip.png-13.8kB][2]
我们甚至可以对多个字段进行`group by`:
```sql
SELECT * FROM `courses` GROUP BY `class`,`student`;
```
执行的结果是:
![ScreenClip.png-14.3kB][3]
最后,我们交换字段顺序对记录进行分组:
```sql
SELECT * FROM `courses` GROUP BY `student`,`class`;
```
执行的结果是:
![ScreenClip.png-17.2kB][4]
这样的结果可能会使人困惑,我们以第一个sql为例,解释下sql执行的过程:
![未命名文件.png-62.2kB][5]
该`sql`首先会按照`class`进行分组得到四张中间表,然后输出的时候将每一个分组的第一个记录组合在一起形成了最终的结果。我们还可以发现,最终的记录是按照`class`进行排序的。这样的顺序并不可靠,具体形成的原因恐怕需要在`Mysql`的底层原理中找到答案。
## Group By还能怎么用
### 与order by结合在一起使用
> 我们需要学生的成绩表,且每个学生每科的成绩按照由大到小的顺序排列

我们可以很自然的写出下面的sql:

SELECT * FROM `courses` GROUP BY `student`,`class` ORDER BY `score` DESC;

然而,执行的结果貌似并不是我们想要的:

![ScreenClip.png-16.6kB][6]
通过观察,我们可以发现,事实上,这个`sql`是将所有的记录按照`score`由大到小的顺序排列了,为什么会出现这样的结果呢?
事实上,这个取决于整个`sql`的执行顺序,真正的执行顺序是 `from` ... `where` ... `group by` ... `order by` ... `select`,`order by` 作用在整个记录,而不是每个分组上。
那么,怎么样能够得到我们期望的结果呢?这里给出我的`sql`实现:
```sql
SELECT * FROM `courses` GROUP BY `student`,`class` ORDER BY `student`,`score` DESC;
```
执行的结果是:
![ScreenClip.png-19.8kB][7]

与having结合在一起使用

我们需要得到所有功课平均分达到60分的同学和他们的均分:

SELECT `student`, AVG(`score`) AS`avg_score`
FROM `courses`
GROUP BY `student`
HAVING AVG(`score`) >= 60
ORDER BY `avg_score` DESC;

执行的结果为:

![ScreenClip (8).png-3.8kB][8]
这里需要注意一个问题:`where` 与 `having`的区别。`where`作用于所有的记录,而`having`则作用于一个分组。
举例说明:
> 假设我们这里需要得到所有功课(除历史课)平均分达到60分的同学和他们的均分:

SELECT `student`, AVG(`score`) AS `avg_score`
FROM `courses`
WHERE `class` <> 'History'
GROUP BY `student`
HAVING AVG(`score`) >= 60
ORDER BY `avg_score` DESC;

执行的结果如下:

![ScreenClip.png-3.1kB][9]
### Group By与Limit
> 我们需要列出均分最高的三门课:

SELECT `class`, AVG(`score`) AS `avg_score`
FROM `courses`
GROUP By `class`
ORDER BY `avg_score` DESC
LIMIT 3;

执行的结果如下:

![ScreenClip.png-3.8kB][10]
我们需要理解的是:`group by`分组的依据,以及`where`过滤条件作用的粒度
如果你觉得你已经理解了`group by`关键字的用法,欢迎移步至Mysql关键字之Group By(二),有点小练习在等着你。。。

Mysql关键字之Group By(一)的更多相关文章

  1. Mysql关键字之Group By(二)

    原文地址,优先更新https://hhe0.github.io 我们在上一节简单介绍了Mysql中group by关键字的用法,没有看过的同学点击这里了解一下; 文中提到的courses表和相关记录可 ...

  2. MySQL关键字

    MySQL关键字 ADD ALL ALTER ANALYZE AND AS ASC ASENSITIVE BEFORE BETWEEN BIGINT BINARY BLOB BOTH BY CALL ...

  3. mysql 关键字于数据库字段于关键字冲突的问题

    如果数据库存储字段 为MySQL关键字,那么在查询或者其他操作时会出错.那么我们应该怎么办, 可能有些人会说,换个字段不就好了啊.当然这样也是可以的,完全没问题. 然而,如果是在无法对数据库进行修改和 ...

  4. MySQL字段命名不能使用的MySQL关键字

    #今天遇到一个问题,把某一字段重新命名为condition时报错,于是联想到可能是MySQL的关键字,用``引起来后,问题解决. #在MySQL数据库中,Table字段不能使用MySQL关键字: #[ ...

  5. mysql distinct跟group by性能

    mysql distinct和group by性能   1,测试前的准备 //准备一张测试表 mysql> CREATE TABLE `test_test` ( ->   `id` int ...

  6. Oracle和MySQL分组查询GROUP BY

    Oracle和MySQL分组查询GROUP BY 真题1.Oracle和MySQL中的分组(GROUP BY)有什么区别? 答案:Oracle对于GROUP BY是严格的,所有要SELECT出来的字段 ...

  7. MySQL 中的反引号(`):是为了区分 MySql 关键字与普通字符而引入的符号;一般,表名与字段名都使用反引号。

    MySQL 中的反引号(`):是为了区分 MySql 关键字与普通字符而引入的符号:一般,表名与字段名都使用反引号.

  8. 在mysql中使用group by和order by取每个分组中日期最大一行数据

    转载自:https://blog.csdn.net/shiyong1949/article/details/78482737 在mysql中使用group by进行分组后取某一列的最大值,我们可以直接 ...

  9. [MySQL 5.6] MySQL 5.6 group commit 性能测试及内部实现流程

    [MySQL 5.6] MySQL 5.6 group commit 性能测试及内部实现流程 http://mysqllover.com/?p=581 尽管Mariadb以及Facebook在long ...

随机推荐

  1. Guava Cache 工具类

    maven依赖 <dependency> <groupId>com.google.guava</groupId> <artifactId>guava&l ...

  2. Django REST framework —— 认证组件源码分析

    我在前面的博客里已经讲过了,我们一般编写API的时候用的方式 class CoursesView(ViewSetMixin,APIView): pass 这种方式的有点是,灵活性比较大,可以根据自己的 ...

  3. HBase数据结构

    1 RowKey 与nosql数据库们一样,RowKey是用来检索记录的主键.访问HBASE table中的行,只有三种方式: 1.通过单个RowKey访问 2.通过RowKey的range(正则) ...

  4. 洛谷 P2746 [USACO5.3]校园网 Network of Schools 题解

    Tarjan 模板题 第一问就是缩点之后看有多少个入度为零的点就好了. 第二问是在缩点后将每个点的入度和出度都求出(只要有入度或出度就置为1),然后比较哪个有值的多,将多的作为答案输出.原因是由题可得 ...

  5. hasura graphql-engine 最近版本的一些更新

    好久没有在关注hasura graphql-engine 了,从最新的release 信息可以看到graphql-engine 已经beta 阶段了,而且目前是v1.0.0-beta.2 估计离生产可 ...

  6. Linux上使用Windows软件

    小书匠 安装完成后,甚至可以在linux上进行视频会议,整个过程分两个步骤: 1.安装deepin-wine 这个步骤看github,Jactor Sue这位老哥弄好了,在这: Deepin-Apps ...

  7. c语言博客作业03--循环结构

    0.展示PTA总分 1.本章学习总结 1.1学习内容总结 循环语句 for语句: for( 表达式1; 表达式2; 表达式3 ) { // 需要执行的语句; } 其执行过程是:表达式 1 首先执行且只 ...

  8. shell脚本编程基础之函数

    函数 作用:代码重用 定义函数: 方法1: function FUNCTION_NAME { #函数名和定义变量名一样,只能包含数字字母下划线,并且不能以数字开头 command } 方法2: FUN ...

  9. 2019 SDN第二次上机作业

    2019 SDN第二次上机作业 1. 利用mininet创建如下拓扑,要求拓扑支持OpenFlow 1.3协议,主机名.交换机名以及端口对应正确,请给出拓扑Mininet执行结果,展示端口连接情况 创 ...

  10. 2019软工实践_Alpha(4/6)

    队名:955 组长博客:https://www.cnblogs.com/cclong/p/11882079.html 作业博客:https://edu.cnblogs.com/campus/fzu/S ...