MySQL运维实战系列:MySQL5.7 Group By 问题

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介:

一、环境

MySQL版本:MySQL5.7.22

表结构:

CREATE TABLE `crm_report_accounting_income` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `contract_id` int(10) NOT NULL,
  `contract_no` varchar(50) NOT NULL,
  `date` int(8) NOT NULL,
  `city_id` int(11) NOT NULL DEFAULT '0' COMMENT '城市id',
  `city_name` varchar(50) DEFAULT NULL,
  `adviser_id` int(10) NOT NULL,
  `adviser_name` varchar(50) DEFAULT NULL,
  `accounting` decimal(15,2) NOT NULL COMMENT 'xx',
  `receivable` decimal(15,2) NOT NULL DEFAULT '0.00' COMMENT '当xx',
  `contract_type` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1:xx合同;2:xx合同;3:xx合同',
  PRIMARY KEY (`id`),
  KEY `contract_id` (`contract_id`),
  KEY `date` (`date`),
  KEY `city_id` (`city_id`)
) ENGINE=InnoDB AUTO_INCREMENT=734525 DEFAULT CHARSET=utf8



二、业务问题


*  基本信息,由于合同号太多,所以这边就以一个有重复数据的合同id为例

dba:aif_db> select contract_id,contract_no,receivable,date from crm_report_accounting_income_2015_online where contract_id = 27310;
+-------------+----------------------------+------------+----------+
| contract_id | contract_no                | receivable | date     |
+-------------+----------------------------+------------+----------+
|       27310 | A00-SHEN-05-2018-06-004613 |    2941.18 | 20180628 |
|       27310 | A00-SHEN-05-2018-06-004613 |    5882.36 | 20180629 |
|       27310 | A00-SHEN-05-2018-06-004613 |    8823.54 | 20180630 |
|       27310 | A00-SHEN-05-2018-06-004613 |   11764.72 | 20180701 |
|       27310 | A00-SHEN-05-2018-06-004613 |   14705.90 | 20180702 |
|       27310 | A00-SHEN-05-2018-06-004613 |   17647.08 | 20180703 |
|       27310 | A00-SHEN-05-2018-06-004613 |   20588.26 | 20180704 |
|       27310 | A00-SHEN-05-2018-06-004613 |   23529.44 | 20180705 |
|       27310 | A00-SHEN-05-2018-06-004613 |   26470.62 | 20180706 |
|       27310 | A00-SHEN-05-2018-06-004613 |   29411.80 | 20180707 |
|       27310 | A00-SHEN-05-2018-06-004613 |   32352.98 | 20180708 |
|       27310 | A00-SHEN-05-2018-06-004613 |   35294.16 | 20180709 |
+-------------+----------------------------+------------+----------+
12 rows in set (0.00 sec)



* 查询每个最新合同的信息,由于合同号太多,所以这边就以一个有重复数据的合同id为例

select contract_no, contract_id, city_name, receivable,date from
(select * from crm_report_accounting_income_2015_online  where contract_id = 27310 ORDER BY `date` desc) p GROUP BY contract_id

+----------------------------+-------------+-----------+------------+----------+
| contract_no                | contract_id | city_name | receivable | date     |
+----------------------------+-------------+-----------+------------+----------+
| A00-xxxx-05-2018-06-xxxxxx |       xxxxx | 沈阳      |    2941.18 | 20180628 |
+----------------------------+-------------+-----------+------------+----------+
1 row in set (0.00 sec)

以上看到的写法,是通过子查询写的,5.6查询没问题,5.7就变成了以上的结果,很明显得到的答案不是业务想要的

究其原因还是因为,MySQL5.7 sql mode更加严格了,如果设置sql_mode = ONLY_FULL_GROUP_BY, 那么以上SQL就会报错

因为sql_mode = ONLY_FULL_GROUP_BY 要求符合SQL 92标准,即:select列表里只能出现分组列(即group by后面的列)和聚合函数(max,min等等)

然而为了兼容5.6,我们设置sql_mode='', 所以我们的Group by 在子查询中就跟5.6就不一致了

当然,我们应该避免不标准的SQL写法,这样的问题,我们的解法就是调整业务的SQL语句,改写成SQL 92标准的语法

那么以上SQL语句应该调整为:

select
    contract_no,
    e.contract_id,
    city_name,
    receivable,
    date
from
    crm_report_accounting_income_2015_online e,
    ( select contract_id , max(date) max_date from  crm_report_accounting_income_2015_online where contract_id = 27310 group by contract_id  ) t
where
    e.contract_id = t.contract_id
    and e.date = t.max_date

+----------------------------+-------------+-----------+------------+----------+
| contract_no                | contract_id | city_name | receivable | date     |
+----------------------------+-------------+-----------+------------+----------+
| A00-xxxx-05-2018-06-004613 |       27310 | xxxx      |   35294.16 | 20180709 |
+----------------------------+-------------+-----------+------------+----------+
1 row in set (0.00 sec)

以上都还是需要业务代码修改,这样如果没有提前发现问题,岂不是会导致业务出错了?有没有更好的办法?

MySQL方面其实还是可以配置相关的参数的:

dba:aif_db> set optimizer_switch='derived_merge=off';
Query OK, 0 rows affected (0.00 sec)

dbadmin:aifangcrm_db> select contract_no, contract_id, city_name, receivable,date from
    -> (select * from crm_report_accounting_income_2015_online  where contract_id = 27310 ORDER BY `date` desc) p GROUP BY contract_id
    -> ;
+----------------------------+-------------+-----------+------------+----------+
| contract_no                | contract_id | city_name | receivable | date     |
+----------------------------+-------------+-----------+------------+----------+
| A00-xxxx-05-2018-06-004613 |       27310 | xxxx      |   35294.16 | 20180709 |
+----------------------------+-------------+-----------+------------+----------+
1 row in set (0.00 sec)

三、总结

  • SQL语法应该要按照标准的SQL92来写
  • 数据库升级到5.7之后,应该提前监控处group by + 子查询的情况,提前告知业务修改业务代码
  • 设置参数也能解决问题,但是这个参数毕竟是5.7新增的,如果关闭后,以后会不会导致其他的bug就不知晓了

最后,还是希望能够修改query 语句到标准语法,如果出现业务问题,可以让业务修改参数快速解决问题,然后再修改语句比较与时俱进

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
2月前
|
运维 关系型数据库 MySQL
运维|MySQL 数据库被黑,心力交瘁
前一阵有一个测试用的 MySQL 数据库被黑了,删库勒索的那种,这里记录一下事情经过,给自己也敲个警钟。
42 2
|
2月前
|
SQL 运维 关系型数据库
MySQL 运维 SQL 备忘
MySQL 运维 SQL 备忘录
48 1
|
4月前
|
关系型数据库 MySQL 数据处理
Mysql关于同时使用Group by和Order by问题
总的来说,`GROUP BY`和 `ORDER BY`的合理使用和优化,可以在满足数据处理需求的同时,保证查询的性能。在实际应用中,应根据数据的特性和查询需求,合理设计索引和查询结构,以实现高效的数据处理。
635 1
|
4月前
|
SQL 关系型数据库 MySQL
在 MySQL 中使用 `GROUP BY` 子句
【8月更文挑战第12天】
108 1
|
4月前
|
关系型数据库 MySQL 数据库连接
绝对干货!从MySQL5.7平滑升级到MySQL8.0的最佳实践分享
绝对干货!从MySQL5.7平滑升级到MySQL8.0的最佳实践分享
209 0
|
4月前
|
运维 关系型数据库 MySQL
在Linux中,MySQL数据库日常运维中涉及哪些关键任务?
在Linux中,MySQL数据库日常运维中涉及哪些关键任务?
|
4月前
|
存储 关系型数据库 MySQL
MySQL中的DISTINCT与GROUP BY:效率之争与实战应用
【8月更文挑战第12天】在数据库查询优化中,DISTINCT和GROUP BY常常被用来去重或聚合数据,但它们在实现方式和性能表现上却各有千秋。本文将深入探讨两者在MySQL中的效率差异,结合工作学习中的实际案例,为您呈现一场技术干货分享。
503 0
|
4月前
|
运维 关系型数据库 MySQL
"MySQL运维精髓:深入解析数据库及表的高效创建、管理、优化与备份恢复策略"
【8月更文挑战第9天】MySQL是最流行的开源数据库之一,其运维对数据安全与性能至关重要。本文通过最佳实践介绍数据库及表的创建、管理与优化,包括示例代码。涵盖创建/删除数据库、表结构定义/调整、索引优化和查询分析,以及数据备份与恢复等关键操作,助您高效管理MySQL,确保数据完整性和系统稳定运行。
429 0
|
5天前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
25天前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
34 1