原文地址,优先更新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. PHP编程实现阳历转换为阴历的方法

    php类: 2 /** 3 *PHP编程实现阳历转换为阴历的方法 4 *根据实际情况所需进行调用 5 * 6 / 7 10 <?php class Lunar { public $MIN_YEA ...

  2. Error while obtaining UI hierarchy XML file: com.android.ddmlib.SyncException: Remote object doesn't

    在使用真机定位页面元素时启动uiautomatorviewer.bat ,报错Error while obtaining UI hierarchy XML file: com.android.ddml ...

  3. flask + websocket实现简单的单聊和群聊

    单聊 from flask import Flask,request,render_template from geventwebsocket.handler import WebSocketHand ...

  4. javascript慕课入门

    1.javascript引用 html里引用: <script type="text/javascript"> ... ... </script> 引用外部 ...

  5. Build Post Office II

    Description Given a 2D grid, each cell is either a wall 2, an house 1 or empty 0 (the number zero, o ...

  6. JavaScript基础05——严格模式

    严格模式: 除了正常运行模式,ECMAscript5添加了第二种运行模式:“严格模式”(strict mode).顾名思义,这种模式是的Javascript在更严格的条件下运行. 严格模式的作用: 1 ...

  7. solidworks 学习 (三)

    汽车轮毂三维建模

  8. H5页面中判断是安卓手机还是ios手机的方法;APP页面中嵌套的H5跳转到APP其他页面的方法。

    (一).在H5页面中,可以直接利用如下的方法来进行判断是安卓还是ios. var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linu ...

  9. pgloader 学习(八) pg 2 pg 简单demo

    pg 数据到pg 数据的迁移,同时支持名称的变更 环境准备 docker-compose文件 内容偏多可以忽略部分 version: "3" services: pgloader- ...

  10. chmod/chown/chgrp/chattr

    权限组合其实就是二进制的组合 注意,用户只能修改属于自己的文件 仅管理员可以修改文件的数组和属主 chmod 三种使用方法 文件的特殊权限 SUID SGID Sticky chowm 修改文件,目录 ...