Mysql only_full_group_by及Error 1055问题分析图解

声明

本文的数据来自网络,部分代码也有所参照,这里做了注释和延伸,旨在技术交流,如有冒犯之处请联系博主及时处理。

: 1 员工表结构和数据初始化SQL脚本

2  当前验证环境CentOS 8 X86 64、mysql 8.0.23、SQL Server 2019

问题描述

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

编写SQL时遇到如下错误,即出现错误 ERROR 1055,SELECT列表不在GROUP BY语句内且存在不函数依赖GROUP BY语句的非聚合字段'trial.B.dname',这是和sql_mode=only_full_group_by不兼容的(即不支持)。

解决方法

Way 1:临时关闭only_full_group_by模式,这种方法通过修改系统变量,重启数据库后失效(修改后需要新开会话或者窗口)。首先查看下当前的sql_mode:

# 查看mysql当前的sql mode
show VARIABLES LIKE 'sql_mode';

-- 1 对系统标量进行全局设置,但数据库重启后失效
set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
-- 2 修改后需在新的回话(窗口)里验证原SQL。

Way 2: 永久关闭only_full_group_by模式,这种方法需要在mysql的配置文件里修改,然后重启。

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

Step 2: 在上述文件内的[mysqld]后追加

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

Step 3:保存配置文件后,重启Mysql即可。

大话group by

啥,这就这么结束?!来来来,别走,我们来拉拉mysql的groupby和sql_mode only_full_group_by模式。开始之前我们得来先做个前期回顾。

SQL 92 group by

首先我们先了解下SQL92标准里关于group by的定义。

SQL-92 and earlier does not permit queries for which the select list, HAVING condition, or ORDER BY list refer to nonaggregated columns that are not named in the GROUP BY clause.

简单的说:SQL-92里 SELECT、HAVING、ORDER后的非聚合字段必须和GROUP BY后的字段保持完全一致。

来个例子瞧瞧呗?如下以sql server2019为例:

--正确的”姿势”
SELECT B.dname,B.deptno,MAX(sal) FROM emp A
JOIN dept B
ON A.deptno = B.deptno
GROUP BY B.deptno,B.dname;--错误的“姿势”
SELECT B.dname,B.deptno,MAX(sal) FROM emp A
JOIN dept B
ON A.deptno = B.deptno
GROUP BY B.deptno;

SQL 99 group by

但是我们经常看到MYSQL的SELECT列表的字段并不在GROUP BY后,这又是咋回事?话不多说,先上几个案例。

-- Msyql:
-- Case 1(此脚本在sql server里报错)
SELECT B.deptno,B.dname,MAX(sal) FROM emp A
JOIN dept B
ON A.deptno = B.deptno
GROUP BY B.deptno;

但为什么mysql就能支持呢?

SQL:1999 and later permits such nonaggregates per optional feature T301 if they are functionally dependent on GROUP BY columns: If such a relationship exists between name and custid, the query is legal. This would be the case, for example, were custid a primary key of customers.

SQL 99登场,这里即是定义了新的标准,如果group by后面的字段是主键(唯一键),而且非聚合字段是函数依赖group by后字段的,那么可以将这些非聚合字段放在SELECT、HAVING、ORDER BY的语句之后。

MySQL implements detection of functional dependence. If the ONLY_FULL_GROUP_BY SQL mode is enabled (which it is by default), MySQL rejects queries for which the select list, HAVING condition, or ORDER BY list refer to nonaggregated columns that are neither named in the GROUP BY clause nor are functionally dependent on them.

Mysql 实现了这种检测函数依赖,这时ONLY_FULL_GROUP_BY SQL 模式登场,mysql里SQL mode设置了这种模式那么如果 group by后的不补全字段或是无函数依赖的字段时非聚合字段放在SELECT、HAVING、ORDER BY的语句之后是不支持的。

有点绕,我们直接开启个案例来说明ONLY_FULL_GROUP_BY有何魔力。

启用only_full_group_by模式

-- Case 2:
SELECT B.dname,MAX(sal) FROM emp A
JOIN dept B
ON A.deptno = B.deptno
GROUP BY B.loc

原因分析,这里group by后的字段loc并没有定义为主键或则唯一键,所以在sql mode是ONLY_FULL_GROUP_BY模式下报错(即不支持)。

我们再来个简单些的例子,即只涉及一张表。

-- Case 3:
--Step 1 创建一张无主键、唯一键的表,插入4条记录(id字段的值不重复)。
CREATE TABLE `test_04251019` (`id` int DEFAULT NULL,`name` varchar(10) DEFAULT NULL,`addr` varchar(12) DEFAULT NULL,`memo` varchar(40) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- Step 2 插入4条记录
INSERT INTO `test_04251019` VALUES ('1', 'hanmeimie', 'Guangzhou', 'Fullbakup');
INSERT INTO `test_04251019` VALUES ('2', 'lilei', 'Guangzhou', 'in increament');
INSERT INTO `test_04251019` VALUES ('4', 'Tom', 'Shanghai', 'no more');
INSERT INTO `test_04251019` VALUES ('5', 'John', 'Shanghai', 'no more_5');-- Step 3 此时我们仿照Case 2写个简单点的聚合语句
SELECT name, MAX(LENGTH(addr)) FROM test_04251019 GROUP BY id;

-- Case 4:
-- Step 1 创建个表类似(test_04251019),但是id定义为主键
CREATE TABLE `test_04251019_key` (`id` int NOT NULL,`name` varchar(10) DEFAULT NULL,`addr` varchar(12) DEFAULT NULL,`memo` varchar(40) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;-- Step 2 插入数据(直接拷贝至test_04251019)
INSERT INTO test_04251019_key(id,name,addr,memo)
SELECT id,name,addr,memo FROM test_04251019;
COMMIT;-- Step 3 新增个唯一字段id_2并更新数据
ALTER TABLE test_04251019_key ADD id_2 int NOT NULL;
UPDATE test_04251019_key SET id_2 = 100+id;
ALTER TABLE test_04251019_key ADD CONSTRAINT unique_id_2 UNIQUE(id_2);-- Step 4 验证group by后含主键、唯一键,非聚合字段并存的情况
SELECT name, MAX(LENGTH(addr)) FROM test_04251019_key GROUP BY id;
SELECT name, MAX(LENGTH(addr)) FROM test_04251019_key GROUP BY id_2;

关闭only_full_group_by模式

一眼不合,我们就关闭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';show variables like 'sql_mode';

这时我们来验证Case 2

Case 3

Case 4:追加案例,针对case 3,如果我们往test_04251019里插入一条记录

-- 插入一条数据(这里id是重复的,已有等于5的了)
INSERT INTO test_04251019 VALUES(5,'Jim','Shanghai2','no more_5_2');-- 再执行聚合函数验证
SELECT name, MAX(LENGTH(addr)) FROM test_04251019 GROUP BY id;

what?“Jim”那条记录对应的GROUP BY统计去哪儿了?为啥不能是我?!

延展阅读

ONLY_FULL_GROUP_BY下的特例(仅有聚合函数和WHERE,这里WHERE是必选项),详见如下截图:

总结

敲黑板

  1. Mysql里的sql mode=only_full_group_by模式是对SQL92 group by的扩展,即对应SQL1999的标准。
  2. SQL92 group by里要求SELECT、HAVING、ORDER BY语句后的字段需要与GROUP BY后的字段严格一致。
  3. Myslq的sql mode=only_full_group_by模式SELECT、HAVING、ORDER BY语句后的字段可以不跟GROUP BY后的字段严格一致,但是GROUP BY的字段需是主键或唯一键时可以写非聚合字段。
  4. Myslq的sql mode非only_full_group_by模式时在表的定义不严格的情况下(如无明确的主键且数据重复时作为GROUP BY后的字段 )执行结果难以解释。
  5. 更多详细细节,详见官网Mannul。
  6. Any question let me know.

一文带你了解mysql sql model的only_full_group_by模式含Error 1055问题分析相关推荐

  1. 一文带你入门flink sql

    文章目录 一文带你入门flink sql 写在前面 环境准备 正文 遇到的一些问题 错误一 错误二 错误三 一文带你入门flink sql 写在前面 本次实战主要是通过Flink SQL Client ...

  2. 精华推荐 | 【JVM深层系列】「GC底层调优系列」一文带你彻底加强夯实底层原理之GC垃圾回收技术的分析指南(GC原理透析)

    前提介绍 很多小伙伴,都跟我反馈,说自己总是对JVM这一块的学习和认识不够扎实也不够成熟,因为JVM的一些特性以及运作机制总是混淆以及不确定,导致面试和工作实战中出现了很多的纰漏和短板,解决广大小伙伴 ...

  3. 【MDX】一文带你搞懂SQL Server Analysis Services 的安装和使用

    目录 Step 1: Install developer and management tools 安装 new stand-alone SQL Server installation or add ...

  4. 一文带你了解MySQL基础

    目录 一,为什么要学习数据库 二,数据库的相关概念 2.1数据库术语 2.2SQL 语法要点 2.3 SQL 分类 数据定义语言(DDL) 数据操纵语言(DML) 事务控制语言(TCL) 数据控制语言 ...

  5. 一文带你了解 MySQL 中的各种锁机制!

    MySQL中的锁机制,按粒度分为行级锁,页级锁,表级锁,其中按用法还分为共享锁和排他锁. 行级锁 行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁. 行级锁能大大减少数据库操作 ...

  6. mysql 获取距离当前最新的记录_一文带你了解 MySQL 中的各种锁机制!

    云栖号资讯:[点击查看更多行业资讯] 在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! MySQL中的锁机制,按粒度分为行级锁,页级锁,表级锁,其中按用法还分为共享锁和排他锁. 行级锁 ...

  7. mysql 导出dmp文件_一文带你了解MySQL主从复制(Master-Slave)

    1.复制概述 Mysql内建的复制功能是构建大型,高性能应用程序的基础.将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台主机的数据复制到其它主机(slaves)上,并重 ...

  8. 一文带你了解MySQL中的各种锁机制!

    云栖号资讯:[点击查看更多行业资讯] 在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! MySQL中的锁机制,按粒度分为行级锁,页级锁,表级锁,其中按用法还分为共享锁和排他锁. 行级锁 ...

  9. 实战:一文带你解决Mysql主从复制日常错误

    使用过Mysql数据库朋友,一定听过读写分离,听的多的,估计耳朵都起茧子了.那么读写分离是怎么实现的呢,最常见的方法就是搭建Mysql的主从复制,主库提供写操作,从库提供读操作,从而达到应用的读写分离 ...

最新文章

  1. mysql查询指定日期
  2. 如何正确访问 redis 中的海量数据?避免事故产生
  3. PHP 基本数据类型
  4. [Unity] TortoiseSVN 的 CheckOut 未响应的解决记录
  5. 大数据学习笔记13:MR案例——显示每年最高温度
  6. SIP应答代码【ZT】
  7. React项目中跨域问题的解决方案
  8. yum用法及程序编译安装
  9. 参数过滤mongodb过滤查询键值
  10. C#中自己动手创建一个Web Server(非Socket实现)
  11. 区块链技术指南学习(一)未来已来
  12. 一次完整的 Http 请求过程
  13. 狮子座与摩羯座 ---转载
  14. mysql数据库连接报错:is not allowed to connect to this mysql server
  15. 数学中奇妙的“金蝉脱壳”(转)
  16. 【九】分布式微服务架构体系详解——共识问题
  17. C++文件操作Read函数
  18. 深度学习结合树搜索求解集装箱预翻箱问题
  19. CSS背景图片 自适应缩放contain/cover
  20. ROS:坐标管理系统

热门文章

  1. Spring Boot 开发web 项目
  2. OpenCASCADE可视化:应用交互服务之本地选择
  3. OpenCASCADE:形状愈合之修复工具
  4. wxWidgets:wxGridUpdateLocker类用法
  5. boost::system::generic_category相关的测试程序
  6. boost::io::ostream_joiner模块相关的测试程序
  7. boost::log::make_exception_handler用法的测试程序
  8. boost::histogram模块实现自定义二维轴的测试程序
  9. boost::gil模块沿 x 轴计算梯度的方法的示例
  10. boost::geometry模块Linestring多边形叠加示例