当前位置: 首页 > news >正文

Mysql ONLY_FULL_GROUP_BY模式详解、group by非查询字段报错

文章目录

  • 一、问题报错
  • 二、ONLY_FULL_GROUP_BY模式
    • 2.1、什么是ONLY_FULL_GROUP_BY?
    • 2.2、为什么要使用ONLY_FULL_GROUP_BY?
    • 2.3、查看sql_mode
  • 三、解决方法
    • 3.1、关闭only_full_group_by模式
      • 3.1.1、方法一:关闭当前会话中的only_full_group_by
      • 3.1.2、方法二:永久关闭only_full_group_by模式
    • 3.2、使用ANY_VALUE()函数
  • 四、其他
    • 4.1、无权限报错
    • 4.2、select后面的字段必须在group by后面出现?当group by遇上唯一索引或主键

以下内容基于Mysql8.0进行讲解ONLY_FULL_GROUP_BY模式。

一、问题报错

Mysql5.7版本以上对group by 分组有了新需求,要求group by 后的字段要与select后查询的字段一致,否则就会报错,报错信息如下:

[2024-09-29 10:48:54] [42000][1055] Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column ‘test.tbl_test.name’ which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

测试用例如下:

create table tbl_test(id int primary key auto_increment,name varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci unique not null,age int comment '年龄',address varchar(50) comment '住址',update_time datetime default null
) comment '测试表';insert into tbl_test(name,age,address,update_time) values
('zhangsan',25,'杭州',now()),
('李四',21,'武汉',now()),
('王五',25,'杭州',now());

在这里插入图片描述
对上述数据同时查询name与age字段,并根据age字段group by 后报错如下:
在这里插入图片描述
原因分析 :MySQL5.7版本及以上默认设置了 mysql sql_mode = only_full_group_by 属性,导致报错。

其中ONLY_FULL_GROUP_BY就是造成这个错误的罪魁祸首了,在这种严格模式下,对于group by聚合操作,若在select中的列没有在group by中出现,那么这个SQL就是不合法的。因为开发写的sql中,select列不在group by从句中,在使用group by时就会报错。

接下来我们一起看一下这个模式的原理以及这种情况如何解决。

二、ONLY_FULL_GROUP_BY模式

2.1、什么是ONLY_FULL_GROUP_BY?

ONLY_FULL_GROUP_BY是MySQL的一个SQL模式(SQL_MODE)之一,它要求在使用GROUP BY语句时,SELECT列表、HAVING条件或ORDER BY列表中的每个列,要么是聚合函数的一部分(如COUNT(), SUM(), AVG()等),要么必须在GROUP BY子句中明确指定。

这一模式的设计初衷是增强查询的准确性和可预测性,避免因为列的不明确引用而导致的数据错误或不一致。

2.2、为什么要使用ONLY_FULL_GROUP_BY?

  • 数据准确性:确保聚合查询的结果符合预期,防止因为非聚合列的不确定行为而导致的数据误导。
  • 一致性:在不同的数据库系统或配置间保持查询行为的一致性,减少迁移或升级时的兼容性问题。
  • 避免歧义:清晰定义查询的意图,减少因查询理解错误而导致的错误。

2.3、查看sql_mode

SELECT @@sql_mode;
或者
select @@GLOBAL.sql_mode;

查询出来的值为:

ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

以下为sql_mode常用值的含义,参考:

ONLY_FULL_GROUP_BY:对于GROUP BY聚合操作,如果在SELECT中的列,没有在GROUP BY中出现,那么这个SQL是不合法的,因为列不在GROUP BY从句中
NO_AUTO_VALUE_ON_ZERO:该值影响自增长列的插入。默认设置下,插入0或NULL代表生成下一个自增长值。如果用户希望插入的值为0,而该列又是自增长的,那么这个选项就有用了。
STRICT_TRANS_TABLES:在该模式下,如果一个值不能插入到一个事务表中,则中断当前的操作,对非事务表不做限制
NO_ZERO_IN_DATE:在严格模式下,不允许日期和月份为零
NO_ZERO_DATE:设置该值,mysql数据库不允许插入零日期,插入零日期会抛出错误而不是警告。
ERROR_FOR_DIVISION_BY_ZERO:在INSERT或UPDATE过程中,如果数据被零除,则产生错误而非警告。如果未给出该模式,那么数据被零除时MySQL返回NULL
NO_AUTO_CREATE_USER:禁止GRANT创建密码为空的用户
NO_ENGINE_SUBSTITUTION:如果需要的存储引擎被禁用或未编译,那么抛出错误。不设置此值时,用默认的存储引擎替代,并抛出一个异常
PIPES_AS_CONCAT:将”||”视为字符串的连接操作符而非或运算符,这和Oracle数据库是一样的,也和字符串的拼接函数Concat相类似
ANSI_QUOTES:启用ANSI_QUOTES后,不能用双引号来引用字符串,因为它被解释为识别符

三、解决方法

对于上述示例中的报错,有以下两种思路解决问题。

  1. 关闭only_full_group_by模式(若没有历史数据的情况下不建议关闭该模式)
  2. 官方说明了:You can achieve the same effect without disabling ONLY_FULL_GROUP_BY by using ANY_VALUE() to refer to the nonaggregated column. 您可以在不禁 ONLY_FULL_GROUP_BY用 的情况下通过ANY_VALUE()引用非聚合列来实现相同的效果。

3.1、关闭only_full_group_by模式

3.1.1、方法一:关闭当前会话中的only_full_group_by

在客户端工具中依次输入以下语句

# 查询当前的sql模式
select @@global.sql_mode;# 去除掉only_full_group_by后再设置到系统中
set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

在这里插入图片描述
注意:这种方法只在当前回话中有效,重启mysql后会失效

再次执行本文开头示例中的sql就不会报错了
在这里插入图片描述

3.1.2、方法二:永久关闭only_full_group_by模式

(1) 找到配置文件/etc/my.cnf(或则关联文件夹找到mysql-server.cnf)

(2) 找到当前配置的sql_mode那行,去掉ONLY_FULL_GROUP_BY;

如果没有,就在文件内的[mysqld]后增加配置:

sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION''

(3)保存配置文件后,重启Mysql。

如果重启后也不会生效,检查下sql_mode的位置是不是不对(放在最后是不会生效的):
在这里插入图片描述

3.2、使用ANY_VALUE()函数

ANY_VALUE():将分到同一组的数据里第一条数据的指定列值作为返回数据。

SELECT any_value(name),age  FROM  tbl_test group by age;

在这里插入图片描述

四、其他

4.1、无权限报错

本人执行

set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

报错了:

[Err] 1227 - Access denied; you need (at least one of) the SUPER privilege(s) for this operation

说明当前用户没有权限;需要联系管理员执行才行;

改服务器配置也同理,如果没有权限,联系管理员。

4.2、select后面的字段必须在group by后面出现?当group by遇上唯一索引或主键

我们上面讲了ONLY_FULL_GROUP_BY模式下select中的列必须在group by中出现,但是经过测试后发现 若group by 后面分组字段是唯一索引或者是主键,那么select后面可以跟其他的列

可能看了这句话不太明白,那么我们用示例演示下, 以下示例基于ONLY_FULL_GROUP_BY模式下:

create table tbl_test(id int primary key auto_increment,-- 注意: name是唯一索引字段name varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci unique not null,age int comment '年龄',address varchar(50) comment '住址',update_time datetime default null
) comment '测试表';insert into tbl_test(name,age,address,update_time) values
('zhangsan',25,'杭州',now()),
('李四',21,'武汉',now()),
('王五',25,'上海',now());

在这里插入图片描述

对上述数据同时查询name与age字段,并根据age字段group by 后报错如下:
在这里插入图片描述
因为开启了ONLY_FULL_GROUP_BY模式,分组字段是age但是查询字段里面包含了name,所以报错了。

select后面的字段必须在group by后面出现吗?测试中偶然发现事实并非如此,看下图示例:
在这里插入图片描述
可以看到上述示例中,group by后面根据name进行分组,select后面跟了age、address字段但是也没报错。

这是为什么呢?难道group by后面分组字段的值不重复就能跟其他字段么?示例中address字段也是不重复的,那么我们用address进行分组试下,结果报错如下:
在这里插入图片描述

经多次测试后发现: 若group by后面分组字段是唯一索引或主键字段,那么select 后面可以跟其他字段。

官方文档中也证实了此结论。
官网地址:https://dev.mysql.com/doc/refman/8.0/en/group-by-handling.html
官方解释是:当group by 后面跟上主键或者不为空唯一索引时,查询是有效的,因为此时的每一笔数据都具有唯一性。
在这里插入图片描述

相关文章:

Mysql ONLY_FULL_GROUP_BY模式详解、group by非查询字段报错

文章目录 一、问题报错二、ONLY_FULL_GROUP_BY模式2.1、什么是ONLY_FULL_GROUP_BY?2.2、为什么要使用ONLY_FULL_GROUP_BY?2.3、查看sql_mode 三、解决方法3.1、关闭only_full_group_by模式3.1.1、方法一:关闭当前会话中的only_full_group_by3…...

设计模式(2)工厂模式

让一个工厂类去生产出对象 (new )来。 我们想要一个 形状,我们用工厂去生产出,圆形,方形。 package com.example.factory2;public interface Shape {void draw(); }public class Square implements Shape {Overridep…...

二分查找算法专题(1)

找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏: 优选算法专题 目录 二分查找算法的介绍 704. 二分查找 34. 在排序数组中查找元素的第一个和 最后一个位置 35. 搜索插入位置 69. x的平…...

ACP科普:SoS不是救命

Scrum of Scrums(SoS)是一种用于协调多个Scrum团队之间工作的扩展框架,特别适用于大型项目或组织中有多个团队同时进行开发的情况。它帮助团队在保持敏捷性的同时,解决跨团队的依赖和协调问题。以下是对Scrum of Scrums的详细介绍…...

C++:模拟实现vector

目录 成员变量与迭代器 size capacity empty 迭代器有关函数 实现默认成员函数的前置准备 reserve ​编辑 ​编辑 push_back 构造函数 无参构造 迭代器区间构造 n个val来进行构造 析构函数 拷贝构造函数 赋值重载 增删查改 clear resize pop_back inser…...

Leecode SQL 184. Department Highest Salary 找出tie

Department Highest Salary 注意!要找出 tie 的 highest salary! Write a solution to find employees who have the highest salary in each of the departments. Return the result table in any order. The result format is in the following ex…...

[Redis][典型运用][缓存]详细讲解

目录 0.什么是缓存?1.使用Redis作为缓存1.为什么用?2.如何用? 2.缓存的更新策略0.前言1.定期生成2.实时生成 3.缓存相关问题1.缓存预热(Cache Preheating)2.缓存穿透(Cache Penetration)3.缓存雪崩(Cache Avalanche)4.缓存击穿(Cache Breakdo…...

GPG error golang 1.19

1. 问题描述及原因分析 在飞腾2000的服务器,OS为Kylin Linux Advanced Server release V10环境下,docker版本为18.09.0(docker-engine-18.09.0-101.ky10.aarch64),基于容器镜像golang:1.19编译新的容器镜像&#xff0…...

Linux如何查看每个文件及文件夹的大小

查看当前目录下每个文件夹的大小,包括其内部所有文件: du -sh *-s:仅显示每个文件夹的总大小,而不是每个文件。-h:以人类可读的格式显示。...

Word样式的同步与重置

有时候我们需要修改Word中的样式,实现排版的个性化。 如何同步样式到其他电脑上? Word中的样式是由Normal.dotm文件控制的,对样式所有的设置和修改,都会保存到这个问题件中,所以我们只需要在设置好样式以后&#xff…...

力扣 —— 跳跃游戏

题目一(中等) 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。 示例 1&…...

SOCKS5代理和HTTP代理哪个快?深度解析两者的速度差异

在现代互联网环境中,使用代理IP已经成为了许多人日常生活和工作的必备工具。无论是为了保护隐私,还是为了访问某些特定资源,代理IP都扮演着重要的角色。今天,我们就来聊聊SOCKS5代理和HTTP代理,看看这两者到底哪个更快…...

工具介绍---效率高+实用

Visual Studio Code (VS Code) 功能特点: 智能代码提示:内置的智能代码提示功能可以自动完成函数、变量等的输入,提高代码编写速度。插件丰富:支持成千上万的扩展插件,例如代码片段、主题、Linting等,能够…...

本地部署开源在线PPT制作与演示应用PPTist并实现异地远程使用

文章目录 前言1. 本地安装PPTist2. PPTist 使用介绍3. 安装Cpolar内网穿透4. 配置公网地址5. 配置固定公网地址 前言 本文主要介绍如何在Windows系统环境本地部署开源在线演示文稿应用PPTist,并结合cpolar内网穿透工具实现随时随地远程访问与使用该项目。 PPTist …...

leetcode_238:除自身以外数组的乘积

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂…...

网络协议详解--IPv6

IPv6产生背景 (1)地址空间的耗尽:因特网呈指数级发展,导致IPv4地址空间几乎耗尽。虽然采用了子网划分、CIDR和NAT地址转换技术,但这没有从根源解决地址耗尽的问题 (2)IP层安全需求的增长&#x…...

阿里云域名注册购买和备案

文章目录 1、阿里云首页搜索 域名注册2、点击 控制台3、域名控制台 1、阿里云首页搜索 域名注册 2、点击 控制台 3、域名控制台...

【经典机器学习算法】谱聚类算法及其实现(python)

🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏: 🏀深度学习_十二月的猫的博客-CSDN博客 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前言 2. 前…...

【Linux】Linux环境基础开发工具使用

Linux开发工具 Linux编辑器-vim使用 1. vim的基本概念 vim的三种模式,分别是命令模式(command mode)、插入模式(Insert mode)和底行模式(last line mode)。 正常/普通/命令模式: …...

Halcon基础系列1-基础算子

1 窗口介绍 打开Halcon 的主界面主要有图形窗口、算子窗口、变量窗口和程序窗口,可拖动调整位置,关闭后可在窗口下拉选项中找到。 2 显示操作 关闭-dev_close_window() 打开-dev_open_window (0, 0, 712, 512, black, WindowHandle) 显示-dev_display(…...

Linux下用qemu-nbd挂载qcow2镜像的完整指南(含LVM/非LVM/ntfs场景)

Linux下用qemu-nbd挂载qcow2镜像的完整指南(含LVM/非LVM/ntfs场景) 当虚拟机突然崩溃或需要从镜像中提取关键数据时,直接挂载qcow2镜像往往是最直接的解决方案。不同于常规磁盘挂载,qcow2镜像可能包含复杂的存储结构——从简单的e…...

别再踩坑了!Docker部署MinIO时,API和Console端口配置的保姆级避坑指南

Docker部署MinIO的端口配置避坑指南:从原理到实战 第一次用Docker部署MinIO时,我花了整整三个小时才搞明白为什么外网始终无法访问。控制台显示服务已启动,本地curl也能返回数据,但就是无法通过浏览器打开管理界面。直到查看日志才…...

Llama-3.2V-11B-cot开源大模型实战教程:双卡4090环境下11B视觉模型快速调用

Llama-3.2V-11B-cot开源大模型实战教程:双卡4090环境下11B视觉模型快速调用 1. 项目概述 Llama-3.2V-11B-cot是基于Meta Llama-3.2V-11B-cot多模态大模型开发的高性能视觉推理工具,专为双卡4090环境深度优化。这个工具解决了视觉权重加载的关键问题&am…...

零基础学习数据库:用快马AI生成你的第一个可操作图书管理系统

作为一个刚接触数据库的小白,最近在InsCode(快马)平台上尝试做了一个图书管理系统项目,整个过程意外地顺利。这里记录下我的学习心得,希望能帮到同样零基础的朋友们。 为什么选择图书管理系统作为入门项目 图书管理系统包含了数据库最基础的…...

Linux字符设备驱动开发与核心架构解析

Linux字符设备驱动开发深度解析1. Linux设备驱动分类与架构Linux内核将设备驱动分为三大类型:字符设备驱动:以字节流形式进行数据读写,如串口、键盘等块设备驱动:以固定大小数据块为单位进行操作,如硬盘、U盘等网络设备…...

告别手动切割:Pixelorama智能精灵图处理方案

告别手动切割:Pixelorama智能精灵图处理方案 【免费下载链接】Pixelorama A free & open-source 2D sprite editor, made with the Godot Engine! Available on Windows, Linux, macOS and the Web! 项目地址: https://gitcode.com/gh_mirrors/pi/Pixelorama …...

Chatbot Arena 排行榜解析:如何为你的聊天机器人优化性能

作为一名刚接触聊天机器人开发的开发者,你可能和我一样,面对琳琅满目的模型和框架感到无从下手。这时候,一个客观、公正的“考场”就显得尤为重要。Chatbot Arena 正是这样一个平台,它通过众包用户进行匿名、随机的模型对战&#…...

STM32CubeMx 软件模拟SPI四种模式

(1)SPI的概念: SPI总线传输一共有4种模式,这4种模式分别由时钟极性(CPOL)和时钟相位(CPHA)来定义。 CPOL:规定了SCK时钟信号空闲状态的电平 CPHA:规定了数据是在SCK时钟的上升沿还是下降沿被采样 模式0&am…...

火星探测器通信系统设计与关键技术解析

1. 火星探测器通信系统设计解析1.1 火星探测任务概述2021年5月15日,中国首次火星探测任务"天问一号"成功着陆火星北半球的乌托邦平原,标志着中国成为继前苏联和美国之后第三个成功实现火星软着陆的国家。此次任务中,"祝融号&q…...

Windows 10/11 下保姆级 APK 逆向环境搭建:JDK、APKTool、JADX 一步到位

Windows 10/11 下保姆级 APK 逆向环境搭建:JDK、APKTool、JADX 一步到位 逆向工程是许多安全研究人员和开发者探索应用内部机制的重要技能。对于 Android 应用来说,搭建一个稳定可靠的逆向环境是第一步。本文将详细介绍如何在 Windows 系统上配置完整的…...