原文地址,优先更新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. Mac下安装oh my zsh之后配置环境变量失效问题

    背景:在刚拿到mac 的时候,使用了默认的bash,由于工作需要在电脑上安装了maven,在~/.bash_profile 文件中添加了maven的配置如下 $ cat ~/.bash_profile ...

  2. 代码优化 - 求数组中的第 K 个最大元素

    题目要求: 解法一: 直接用 sort 从大到小排序,取第 k 个 var findKthLargest = function (nums, k) { nums.sort((a, b) => { ...

  3. python测试开发django-rest-framework-64.序列化(serializers.Serializer)

    前言 REST framework中的serializers与Django的Form和ModelForm类非常像.我们提供了一个Serializer类,它为你提供了强大的通用方法来控制响应的输出, 以 ...

  4. 微信小程序~上拉加载onReachBottom

    代码: //页面上拉触底事件的处理函数 onReachBottom(e) { console.log("底部")// 滚动到页面执行 该 方法 wx.showToast({ tit ...

  5. Linux 安装Anaconda 提示“bunzip2: command not found”

    问题: 安装Anaconda 过程中提示缺少“bunzip2” 解决思路: 由于缺少bunzip2 包,需要通过yum 方式安装bzip2 yum install -y bzip2 Linux bun ...

  6. 在vue项目中使用axios

    安装 cnpm i axios --save-dev 在项目main.js中全局引用 import axios from "axios" Vue.prototype.$http=a ...

  7. 时间戳显示为多少分钟前,多少天前的JS处理,JS时间格式化,时间戳的转换

    var dateDiff = function (timestamp) { // 补全为13位 var arrTimestamp = (timestamp + '').split(''); for ( ...

  8. LightOJ - 1318 - Strange Game(组合数)

    链接: https://vjudge.net/problem/LightOJ-1318 题意: In a country named "Ajob Desh", people pla ...

  9. 基于Kafka的实时计算引擎如何选择?(转载)

    1.前言 目前实时计算的业务场景越来越多,实时计算引擎技术及生态也越来越成熟.以Flink和Spark为首的实时计算引擎,成为实时计算场景的重点考虑对象.那么,今天就来聊一聊基于Kafka的实时计算引 ...

  10. 开发框架Express

    一.使用原因 由于nodejs原生的http核心模块在某些方面不足以应对开发需求,所以就需要使用框架来加快开发效率,让代码更高度统一.在nodejs中有许多web开发框架,以下介绍Express的使用 ...