事前准备

为了故事的顺利发展,我们先得建一个表:

CREATE TABLE student_score (

number INT(11) NOT NULL,

name VARCHAR(30) NOT NULL,

subject VARCHAR(30) NOT NULL,

score TINYINT(4) DEFAULT NULL,

PRIMARY KEY (number,subject)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这个student_score表是用来存储学生成绩的,我们为这个条填充一些数据,填充后的效果就像这样:

mysql> SELECT * FROM student_score;

+----------+-----------+-----------------------------+-------+

| number | name | subject | score |

+----------+-----------+-----------------------------+-------+

| 20180101 | 杜子腾 | 母猪的产后护理 | 78 |

| 20180101 | 杜子腾 | 论萨达姆的战争准备 | 88 |

| 20180102 | 杜琦燕 | 母猪的产后护理 | 100 |

| 20180102 | 杜琦燕 | 论萨达姆的战争准备 | 98 |

| 20180103 | 范统 | 母猪的产后护理 | 59 |

| 20180103 | 范统 | 论萨达姆的战争准备 | 61 |

| 20180104 | 史珍香 | 母猪的产后护理 | 55 |

| 20180104 | 史珍香 | 论萨达姆的战争准备 | 46 |

+----------+-----------+-----------------------------+-------+

8 rows in set (0.00 sec)

GROUP BY是在干什么?

我们知道MySQL提供了一系列的聚集函数,诸如:COUNT:统计记录数。

MAX:查询某列的最大值。

MIN:查询某列的最小值。

SUM:某列数据的累加总和。

AVG:某列数据的平均数。

比方说我们想查看一下student_score表中所有人成绩的平均数就可以这么写:

mysql> SELECT AVG(score) FROM student_score;

+------------+

| AVG(score) |

+------------+

| 73.1250 |

+------------+

1 row in set (0.00 sec)

如果我们只想查看《母猪的产后护理》这个科目的平均成绩,那加个WHERE子句就好了:

mysql> SELECT AVG(score) FROM student_score WHERE subject = '母猪的产后护理';

+------------+

| AVG(score) |

+------------+

| 73.0000 |

+------------+

1 row in set (0.00 sec)

同理,我们也可以单独查看《论萨达姆的战争准备》这门课程的平均成绩:

mysql> SELECT AVG(score) FROM student_score WHERE subject = '论萨达姆的战争准备';

+------------+

| AVG(score) |

+------------+

| 73.2500 |

+------------+

1 row in set (0.00 sec)

这时候问题来了,如果这个student_score表中存储了20门科目的成绩信息,那我们怎么单独的得到这20门课程的平均成绩呢?单独写20个查询语句?那要是有100门课呢?

很显然,不能傻兮兮的写一百个语句,设计MySQL的大叔给我们提供了分组的概念。我们可以按照某个列将表中的数据进行分组,比方说我们现在按照subject列对表中数据进行分组,那么所有的记录就会被分成2组,如图所示:

让MySQL产生这样子的分组的语句就是GROUP BY子句,我们只要在GROUP BY后边把需要分组的列写上就好,然后在查询列表处就可以针对每一个分组来写相应的聚集函数去统计该分组,就像这样:

mysql> SELECT subject, AVG(score) FROM student_score GROUP BY subject;

+-----------------------------+------------+

| subject | AVG(score) |

+-----------------------------+------------+

| 母猪的产后护理 | 73.0000 |

| 论萨达姆的战争准备 | 73.2500 |

+-----------------------------+------------+

2 rows in set (0.00 sec)

报错和解决

可以从上边带有GROUP BY子句的查询语句中看出来,我们只在查询列表处放了分组列subject以及对该分组中的记录调用的聚集函数AVG,那如果我们把不是分组列的字段也放到查询列表中会出现啥情况:

mysql> SELECT subject, name, AVG(score) FROM student_score GROUP BY subject;

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

mysql>

可以看到报错了,为啥会报错呢?回想一下我们使用GROUP BY子句的初衷,我们只是想把记录分为若干组,然后再对各个组分别调用聚集函数去做一些统计工作。本例中的查询列表处放置了既非分组列、又非聚集函数的name列,那我们想表达啥意思呢?从各个分组中的记录中取一个记录的name列?该取哪条记录为好呢?比方说对于'母猪的产后护理'这个分组中的记录来说,name列的值应该取杜子腾,还是杜琦燕,还是范统,还是史珍香呢?这个我们也不知道,所以把非分组列放到查询列表中会引起争议,导致结果不确定,所以设计MySQL的大叔才会为上述语句报错。

不过有的同学会说,假如分组后的某个分组的某个非分组列的值都一样,那我把该非分组列加入到查询列表中也没啥问题呀。比方说按照subject列进行分组后,假如在'母猪的产后护理'的分组中各条记录的name列的值都相同,在'论萨达姆的战争准备'的分组中各条记录的name列的值也都相同,那么我们把name列放在查询列表中也没啥问题。可能设计MySQL的大叔觉得这种说法也有点儿道理,他们竟然同意在一些情况下把非分组列也放到查询列表中,这就设计到一个称之为sql_mode的系统变量,我们先看一下在我的电脑上这个系统变量的值:

mysql> SHOW VARIABLES LIKE 'sql_mode';

+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+

| Variable_name | Value |

+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+

| sql_mode | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |

+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+

1 row in set (0.02 sec)

哇唔,好长的一段。不过大家不必在意,我们只关心其中一个称之为ONLY_FULL_GROUP_BY的家伙。只要sql_mode的值里边有这个东东,MySQL服务器就“比较正常”(也就是不允许非分组列放到查询列表中),但是如果我们把这个东东从sql_mode系统变量中移除(移除这个东东只要重新设置一下这个系统变量,把这个东东从值里边去除掉就好,我们现在不必要关心值里边儿后边那一坨东西是干嘛的,照着抄下来就好):

mysql> set sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

Query OK, 0 rows affected (0.00 sec)

然后再执行上边那个曾经报错的语句:

mysql> SELECT subject, name, AVG(score) FROM student_score GROUP BY subject;

+-----------------------------+-----------+------------+

| subject | name | AVG(score) |

+-----------------------------+-----------+------------+

| 母猪的产后护理 | 杜子腾 | 73.0000 |

| 论萨达姆的战争准备 | 杜子腾 | 73.2500 |

+-----------------------------+-----------+------------+

2 rows in set (0.00 sec)

看,这回就不会报错了。但这是个好事儿么?个人觉得不是,因为MySQL服务器也不能保证结果集中的name列的值到底是分组中的哪条记录的。大家在日常工作中,也希望尽量不要用这个投机取巧的功能,没啥卵用,而且容易产生错误。小贴士: 不同MySQL版本中sql_mode的值可能默认包含ONLY_FULL_GROUP_BY这个家伙,也可能不包含ONLY_FULL_GROUP_BY这个家伙,也就是说不同MySQL版本中可能默认不支持查询列表中包含非分组列,也可能默认支持查询列表中包含非分组列。

来源:微信公众号

作者:小孩子4919

mysql的group by语句不会产生_MySQL:为什么查询列表中多了它,GROUP BY语句就会报错呢?...相关推荐

  1. MySQL在windows系统中修改datadir路径后无法启动问题,报错1067

    windows server2008下如何更改MySQL数据库的目录的帖子已经很多了,这里简单介绍一个步骤,如果不成功请先查看其它帖子. 更改默认的mysql数据库目录将 C:\Documents a ...

  2. mysql的过程返回执行成功与失败_进行数据库操作的时候,操作错误或者失败,但是不报错...

    首先需要注意的是: PHP代码的运行错误 和 PHP与MySQL中交互过程中,MySQL中发生的错误,并不一定是同步的. Case 1:使用PDO,没有设置PDO::ATTR_ERRMODE PDO在 ...

  3. mysql中len是什么意思_MySQL的查询计划中ken_len的含义

    本文首先介绍了MySQL的查询计划中ken_len的含义:然后介绍了key_len的计算方法:最后通过一个伪造的例子,来说明如何通过key_len来查看联合索引有多少列被使用. key_len的含义 ...

  4. mysql用in报错_Mysql子查询IN中使用LIMIT

    学习下Mysql子查询IN中使用LIMIT的方法. 这两天项目里出了一个问题,mysql LIMIT使用后报错. 需求是这样的,我有3张表,infor信息表,mconfig物料配置表,maaply物料 ...

  5. mysql cluster 宕机 恢复_mysql cluster 集群恢复不起来,还请大神赐教?报错-问答-阿里云开发者社区-阿里云...

    mysql cluster 集群原本使用的几乎全是内存表,后来随着数据的增长,把大的内存表迁移到磁盘表了,之后集群出现6050错误,整个集群挂掉:之后重新启动集群一直启动不起来... ----以下是集 ...

  6. mysql导入csv文件 第一行有问题_mysql 导入 csv文件中数据,只能导入第一行

    用workbench导入csv数据,只能导入数据的第一行,也就是标注每一列的列名的那一行. 但问题是,每次导入完成时,系统提示已经导入了500条记录(这个文件中的确有500条记录),可是刷新数据库后打 ...

  7. mysql取最接近的两个值_Mysql:获取一行中另一个字段的最高值和最...

    我有一个(MySQL)表,有两个日期/时间字段:开始和结束(每个类型的日期时间).我需要一个查询,它为我提供从开始的最低值和特定用户的最高值和定义的日期.我终于成功了以下查询: SELECT job. ...

  8. MySQL与oracle报错显示_Oracle中判断表是否存在再删除表避免报错与MySql和SqlServer的不同...

    不同数据库中drop a table if it exists的不同: In MySQL it is pretty easy to drop a table if it exists already. ...

  9. mysql 删除另一个表中的_mysql – 在一个查询SQL中删除两个表中的记录

    我有两张桌子 EMPGROUP_TBL SEQID | MASTERID | BUSINESS_UNIT | DIVISION | SUB_DIVISION | CLASSIFICATION | SU ...

  10. 处理sharepoint 列表中的 person or group类型字段

    如果直接取列表项的值,person or group 类型字段会是 userid;#value 的样式,所以对此类型字段需转换成 spuser 处理 SPUser test = GetSPUser(o ...

最新文章

  1. 13本干货书籍,百余篇原创来了
  2. laravel-mix 使用
  3. python【蓝桥杯vip练习题库】ADV-147学霸的迷宫(广搜 bfs经典问题)
  4. 让无数社群为自己打工?你要用好这6大驱动力
  5. Alcatraz插件安装问题
  6. 深入理解软件和硬件(国庆精彩活动预告)
  7. pytdx 获取板块指数_能否增加一个通过股票代码,板块指数代码获得中文名称的接口?...
  8. OEA 中 WPF 树型表格虚拟化设计方案
  9. 语音情感识别--RNN
  10. 怎么在InfoPath Web浏览器表单中弹出对话框?
  11. BMW Trojan 样本分析
  12. java 抛体运动6_抛体运动的公式
  13. PC端微信dat还原工具源码分享【福利】
  14. 为什么有那么多编码员音乐家?
  15. html360全景图原理,html360°全景展示 示例
  16. arduino 天下第一(暴论) -- 智能猫眼与 SDDC 连接器移植到 arduino 上
  17. OpenStack部署及创建云主机实例
  18. 4G、5G多卡聚合技术在打造智慧城市中的解决方案
  19. JAVA有关NFC读卡器读取数据
  20. 关于C语言教材的一点疑惑。为什么现在国内各大高校仍选用谭浩强的《C 程序设计》为教材?

热门文章

  1. Unity功能记录(七)------ UGUI获取UI在Canvas下的坐标/根据UI位置获取屏幕图片/二维码识别
  2. 2020年高效搬砖必备的IDEA插件(附安装包)
  3. 超全汇总 | 基于Camera的3D目标检测算法综述!(单目/双目/伪激光雷达)
  4. andriod 无网络逻辑设置和判断
  5. 德州大学奥斯汀分校计算机专业排名,德州大学奥斯汀分校专业排名一览及最强专业推荐(USNEWS美国大学排名)...
  6. 解析:为什么程序员应该有一台Mac个人电脑?
  7. Tenth season eleventh episode,Ross is Monica‘s first kiss?????the stripper cried?????
  8. 解决idea百度翻译无法使用的问题
  9. 凉宫春日的忧郁第五章
  10. Retrofit自定义CallAdapterFactory