从 MySQL 5.7 到 8.0:理解 GROUP BY 的新规则与实战优化20241112

🎯 从 MySQL 5.7 到 8.0:理解 GROUP BY 的新规则与实战优化

🔎 引言

随着 MySQL 的不断升级,从 5.7 到 8.0,不仅性能得到提升,其对 SQL 标准的严格执行也显著提高。GROUP BY 的行为变化就是一个典型例子。对开发者而言,MySQL 8.0 强制遵守 ONLY_FULL_GROUP_BY 规则,虽然提高了数据一致性,但也为老代码迁移带来了不小的挑战。

本文将从 问题背景 出发,通过 报错分析 和 案例复盘,探讨如何应对 MySQL 升级带来的挑战,同时总结出一套高效的解决方案。

🌟 一、问题背景:MySQL 升级带来的挑战

1. 什么是 GROUP BY?

GROUP BY 是一种将数据按字段分组的 SQL 操作,通常用于统计、聚合和分析场景。示例如下:

SELECT department, COUNT(*) AS employee_count
FROM employees
GROUP BY department;

2. MySQL 5.7 的行为

  • 默认启用了 ONLY_FULL_GROUP_BY 模式,但执行较为宽松。
  • 某些情况下,未完全符合规则的查询也能隐式运行。

3. MySQL 8.0 的行为

  • 严格执行 ONLY_FULL_GROUP_BY 模式。
  • 未分组字段或未使用聚合函数的字段会直接报错。
  • 示例:
SELECT column1, column2, MAX(column3)
FROM table_name
GROUP BY column1;

在 MySQL 8.0 中,若 column2 未出现在 GROUP BY 或未使用聚合函数,将报错:

Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'column2' which is not functionally dependent on columns in GROUP BY clause.

🚨 二、常见报错与原因

1. 报错示例 1

SELECT column1, column2
FROM table_name
GROUP BY column1;
  • 错误信息:
Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'column2'.

原因:column2 既未分组也未聚合,违反了 SQL 标准。

2. 报错示例 2

SELECT column1, MAX(column2), column3
FROM table_name
GROUP BY column1;
  • 错误信息:
Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'column3'.

原因:column3 未分组或聚合,与 ONLY_FULL_GROUP_BY 规则冲突。

🔧 三、解决方案

方法 1:修改 SQL 查询 🛠️

调整查询以符合 GROUP BY 规则:
1. 所有未聚合字段必须出现在 GROUP BY 中。
2. 为未分组字段使用聚合函数。

示例改写:

-- 错误写法
SELECT column1, column2
FROM table_name
GROUP BY column1;-- 正确写法
SELECT column1, MAX(column2) AS max_column2
FROM table_name
GROUP BY column1;
  • 优缺点:
    • ✅ 优点:符合标准,解决问题的长远之道。
    • ❌ 缺点:需要对旧代码进行大规模修改。

方法 2:调整 MySQL 配置 ⚙️

通过调整 MySQL 的 sql_mode 配置,禁用 ONLY_FULL_GROUP_BY:

步骤:

1. 检查当前 sql_mode:
SELECT @@GLOBAL.sql_mode;

输出示例:

STRICT_TRANS_TABLES,ONLY_FULL_GROUP_BY,NO_ENGINE_SUBSTITUTION
2. 移除 ONLY_FULL_GROUP_BY:
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', ''));
3. 修改配置文件,永久禁用:编辑 /etc/mysql/my.cnf:
[mysqld]
sql_mode=STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
4. 重启 MySQL 服务:
sudo systemctl restart mysql

验证:

SELECT @@GLOBAL.sql_mode;

输出中不应包含 ONLY_FULL_GROUP_BY。

优缺点:
• ✅ 优点:快速解决问题,无需修改 SQL。
• ❌ 缺点:可能导致聚合结果错误,需谨慎使用。

🔍 四、插曲:配置文件冲突与排查

1. 配置文件加载顺序

MySQL 加载配置文件的顺序如下:
1. /etc/my.cnf
2. /etc/mysql/my.cnf
3. /etc/mysql/conf.d/.cnf
4. /etc/mysql/mysql.conf.d/
.cnf

  • 问题:
    多个配置文件中定义了 sql_mode,后加载的文件会覆盖前面的设置。

2. 如何发现冲突?

  • 检查所有配置文件:
sudo grep -R "sql_mode" /etc/mysql/
  • 查看实际加载的配置文件:
mysql --help | grep "Default options"
  • 验证实际生效的 sql_mode:
SELECT @@GLOBAL.sql_mode;

3. 解决冲突的最佳实践

•	将主要的 sql_mode 定义放在 /etc/mysql/my.cnf。
•	针对工具(如 mysqldump)的特殊需求,单独在 /etc/mysql/conf.d/*.cnf 中配置。

📚 五、实际案例复盘

案例 1:查询菜单类型统计

表名:eb_system_menu
表结构:

+------------+--------------+
| Field      | Type         |
+------------+--------------+
| id         | int          |
| menu_type  | varchar(2)   |
| name       | varchar(100) |
+------------+--------------+

需求:统计每种菜单类型的数量。

SELECT menu_type, COUNT(*) AS count
FROM `ydkj-mall`.`eb_system_menu`
GROUP BY menu_type;

案例 2:用户状态分布统计

表名:eb_user
表结构:

+------------+--------------+
| Field      | Type         |
+------------+--------------+
| uid        | int          |
| status     | tinyint(1)   |
| nickname   | varchar(100) |
+------------+--------------+

需求:统计每种状态的用户数量。

SELECT status, COUNT(*) AS user_count
FROM `ydkj-mall`.`eb_user`
GROUP BY status;

🎯 六、总结与最佳实践

1. 理解 MySQL 的变化

MySQL 8.0 的严格模式符合标准化要求,虽然迁移成本较高,但能显著提高数据一致性。

2. 合理选择解决方案

  • 修改 SQL 查询是最推荐的长远方案。
  • 调整 sql_mode 可作为短期过渡,但需严格测试。

3. 配置管理的建议

  • 集中管理 sql_mode,避免多文件冲突。
  • 使用工具检查实际生效的配置,确保一致性。

🎉 附录:常用 SQL 验证命令

-- 查看当前模式
SELECT @@GLOBAL.sql_mode;-- 查看表结构
DESCRIBE `table_name`;-- 显示加载的配置文件
mysql --help | grep "Default options";

通过对 MySQL 的深入分析和实战操作,相信你已经掌握了解决 GROUP BY 规则冲突的技巧。希望这篇文章能帮助你在数据库升级中游刃有余,轻松应对变化! 😊

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/59388.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【activiti工作流源码集成】springboot+activiti+mysql+vue+redis工作流审批流集成整合业务绑定表单流程图会签驳回

工作流集成实际项目案例,demo提供 源码获取方式:本文末个人名片直接获取。 前言 activiti工作流引擎项目,企业erp、oa、hr、crm等企事业办公系统轻松落地,请假审批demo从流程绘制到审批结束实例。 一、项目形式 springbootvue…

CKA认证 | Day2 K8s内部监控与日志

第三章 Kubernetes监控与日志 1、查看集群资源状态 在 Kubernetes 集群中,查看集群资源状态和组件状态是非常重要的操作。以下是一些常用的命令和解释,帮助你更好地管理和监控 Kubernetes 集群。 1.1 查看master组件状态 Kubernetes 的 Master 组件包…

推荐一款好用的postman替代工具2024

Apifox 是国内团队自主研发的 API 文档、API 调试、API Mock、API 自动化测试一体化协作平台,是非常好的一款 postman 替代工具。 它通过一套系统、一份数据,解决多个系统之间的数据同步问题。只要定义好接口文档,接口调试、数据 Mock、接口…

gdb调试redis。sudo

1.先启动redis-server和一个redis-cli。 2.ps -aux|grep reids查看redis相关进程。 3.开始以管理员模式附加进程调试sudo gdb -p 2968.注意这里不能不加sudo,因为Redis 可能以 root 用户启动,普通用户无法附加到该进程。否则就会出现可能下列情形&#…

YUM 的使用

YUM 是一个用于 Fedora 和 Red Hat 以及 CentOS 操作系统的前端软件包管理器,它可以自动处理依赖关系并一次性安装所有必需的软件包。 镜像站点选择 1. 备份原有的镜像源配置文件 系统默认的 yum 镜像源配置文件存储在 /etc/yum.repos.d/ 目录下,可以…

力扣 LeetCode 242. 有效的字母异位词(Day3:哈希表)

解题思路: 哈希表三种数据结构的选择 1. 数组:适用于数据量小的情况 2. set:适用于数据量大的情况 3. map:适用于key-value 什么时候用哈希表? 给你一个元素,判断该元素在这个集合里是否出现过 本题使…

【MYSQL】锁详解(全局锁、表级锁、行级锁)【快速理解】

目录 一、全局锁 二、表级锁 1.表锁 2.元数据锁 3.意向锁 三、行级锁 1. 行锁 2.间隙锁 3.临建锁 锁是处理并发情况下,对数据的一致性的关键因素,也是并发情况下对效率影响非常大的。 1、全局锁:锁定表中所有数据。 2、表级锁:…

蓝桥杯每日真题 - 第11天

题目:(合并数列) 题目描述(14届 C&C B组D题) 解题思路: 题意理解:给定两个数组,目标是通过若干次合并操作使两个数组相同。每次合并操作可以将数组中相邻的两个数相加&#xff…

contos7.9 部署3节点 hadoop3.4 集群 非高可用

contos7.9 部署3节点 hadoop3.4 集群 非高可用 contos7.9 部署3节点 hadoop3.4 集群 非高可用环境信息服务器角色分配服务器配置服务器配置初始化 init_server.sh配置主机名映射所有节点配置 hosts文件 配置免密登录 hadoop 安装环境配置下载安装包下载 jdk1.8hadoop3.4 分发安…

人工智能:重塑医疗、企业与生活的未来知识管理——以HelpLook为例

一、医疗行业:AI引领的医疗革新 随着人工智能(AI)技术的持续飞跃,我们正身处一场跨行业的深刻变革之中。在医疗健康的广阔舞台上,人工智能技术正扮演着日益重要的角色。它不仅能够辅助医生进行病例的精准诊断&#xf…

第四十五章 Vue之Vuex模块化创建(module)

目录 一、引言 二、模块化拆分创建方式 三、模块化拆分完整代码 3.1. index.js 3.2. module1.js 3.3. module2.js 3.4. module3.js 3.5. main.js 3.6. App.vue 3.7. Son1.vue 3.8. Son2.vue 四、访问模块module的state ​五、访问模块中的getters ​六、mutati…

论文笔记 SuDORMRF:EFFICIENT NETWORKS FOR UNIVERSAL AUDIO SOURCE SEPARATION

SUDORMRF: EFFICIENT NETWORKS FOR UNIVERSAL AUDIO SOURCE SEPARATION 人的精神寄托可以是音乐,可以是书籍,可以是运动,可以是工作,可以是山川湖海,唯独不可以是人。 Depthwise Separable Convolution 深度分离卷积&a…

69页可编辑PPT | 大数据基础知识培训课件

课件全面介绍了大数据的基础知识,包括大数据的定义、特征、发展演进、产业链、关键技术以及市场规模等多个方面,旨在为观众提供一个关于大数据领域的综合性概览。 大数据基本概念 广义的定义(哲学) :大数据,是指物理世界到数字世界的映射和提…

仓储管理系统-综合管理(源码+文档+部署+讲解)

本文将深入解析“仓储管理系统-综合管理”的项目,探究其架构、功能以及技术栈,并分享获取完整源码的途径。 系统概述 仓储管理系统-综合管理是一个全面的仓库管理解决方案,旨在通过集成多种功能模块来优化仓库操作和管理流程。该系统提供了…

MYSQL中的两种转义操作

在 MySQL 中,转义字符用于处理特殊字符,以防止语法错误或 SQL 注入攻击,而单双引号都是需要重点注意的字符 可以用转义符\ 和 两个连续的引号 来起到转义引号的作用 转义符转义: 这是users表中的数据 如果查询admin 或者 admin" 用户,可以用转义符\ 两个连…

引领企业未来数字基础架构浪潮,中国铁塔探索超大规模分布式算力

分布式算力被中国信通院列入“2024政企数智化转型十大关键词”。中国信通院指出,随着新一代通信规模建设和边缘计算应用的持续部署,越来越多的应用运行和数据生产处理在边端侧开展,这对于传统算力基础设施的部署、调度提出了新要求&#xff0…

【数据结构】快排之三路划分

目录 一、前言 二、 快排性能的关键点分析 三、 三路划分基本思想 四、 思路分析 五、提醒 六、代码实现 一、前言 继续对快速排序的深入优化进行探讨 二、 快排性能的关键点分析 决定快排性能的关键点是每次单趟排序后,key对数组的分割。 如果每次选key都能…

Kafka面试题解答(一)

1.kafka消息发送的流程? 生产者:在消息发送的过程中涉及到了两个线程:main线程和sender线程。在main线程中创建了一个双端队列RecordAccumulator(默认32m)。main线程将消息发送RecordAccumulator,sender线程不断地从R…

基于yolov8、yolov5的番茄成熟度检测识别系统(含UI界面、训练好的模型、Python代码、数据集)

摘要:番茄成熟度检测在农业生产及质量控制中起着至关重要的作用,不仅能帮助农民及时采摘成熟的番茄,还为自动化农业监测提供了可靠的数据支撑。本文介绍了一款基于YOLOv8、YOLOv5等深度学习框架的番茄成熟度检测模型,该模型使用了…

Oracle 数据库创建导入

注意:本教程中的有些命令您可能并不熟悉,但没关系,只需按照说明一步一步创建示例数据库即可。在之后的教程中,会详细介绍每个命令。 1.创建新用户并授予权限 1.1.打开 首先,启动 SQL plus 程序的命令行:…