Featured image of post SQL——Group By的使用及子句执行顺序

SQL——Group By的使用及子句执行顺序

介绍SQL中的分组条件、语法,以及在有Where、Order By、Having子句时的执行顺序

Group By概述

  顾名思义,Group By是将数据分组,将具有相同数据的行放在同一组中,使用Group By我们能对表的数据在可视化的基础上更加清晰的观察同类别、相同值的数据组。

注:Group By是先经过排序后再分组。

Group By用法

  首先最简单的Group By用法就是对单一的列进行分组,比如我想统计每个学校的学生人数:

1
2
3
SELECT School, COUNT(*) AS `StudentNum`
FROM Mytable
GROUP BY School;

  利用School字段进行分组,然后统计每一组的行数,这样学生的人数就统计出来了。这里面要说一下Group By的一个语法注意事项,在Select中出现的字段,只能被包含在Group By语句中作为条件,或者是在聚合函数中使用。这一点很容易就被遗漏了,而且在不同的MySQL版本中会出现不一样的提示和报错。

  首先表的内容如下,

  然后执行如下语句会报错,如图:

  这里的S1.Score,就没用被作为Group By的条件,所以不能使用,但是如果是下面这样,将两个字段都作为条件当作列就可以,或者是只用S1.score也是可以的,如图:

  但是呢,之所以我这里强调一下这一点是因为,我在一些刷题网站或者其他地方的虚拟终端、控制台上敲代码的时候,发现有的人这样写的结果竟然没有问题,通过了,还可以作为某些问题的解法,这就让我产生了一些疑惑。首先看一下这段报错。

1
2
3
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains 
nonaggregated column 'test.S1.Score' which is not functionally dependent on columns in 
GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

  这段错误前半部分就是说明的就是Group By的那个语法要求,如果在Select中出现的列,没有在Group By中出现,或者是聚合函数中使用,那么这个SQL就不合法,但是后半部分this is incompatible with sql_mode=only_full_group_by,问题就在这里,我后来去查了一下,在MySQL 5.7.5版本之前only_full_group_by默认是不开启的,所以有个比较狠的方法就是改库。在命令行输入以下命令查看:

1
2
3
mysql> SELECT @@GLOBAL.sql_mode;

mysql> SELECT @@SESSION.sql_mode;

  查询后如图:

  会查询到only_full_group_by是开启的,所以把他关闭即可,输入如下命令:

1
2
mysql> set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
mysql> set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

  之后就在MySQL 5.7.5之后的版本使用了。

Group By和Having的使用及子句执行顺序

  这里首先介绍一下Where和Having的使用区别:

Where子句是在我们查询结果的执行分组前进行过滤,且条件不能使用聚合函数。

Having子句是在分组之后进行过滤,条件可以使用聚合函数。

  所以我们能得到,正常的写法规则,Where要在Group By之前,而Having要在Group By之后,那么接下来就是完整的执行顺序:

  • 先执行Where对行进行筛选,返回第1个结果集;
  • 再执行Group By进行分组,返回第2个结果集;
  • 执行Select,返回第3个结果集;
  • 对结果集进行Having筛选,返回第4个结果集;
  • 最后执行Order By进行排序

  以上执行顺序,配合代码自己梳理一遍会更加的理解清晰。

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy