解决MySQL 5.7.9版本sql_mode=only_full_group_by问题

当MySQL的版本为5.7.9及以上时,启动sql_mode为only_full_group_by时,可能会导致部分SQL语句执行异常。本攻略将会介绍如何解决这个问题。

问题描述

在MySQL 5.7.9及以上版本中,启动sql_mode为only_full_group_by时,如果有GROUP BY的SQL语句中包含非GROUP BY中的字段,MySQL会抛出如下异常。

ERROR 1055 (42000): Expression #N of SELECT list is not in GROUP BY clause and contains nonaggregated column ...

解决方法

1. 修改MySQL配置文件

可以直接修改MySQL的配置文件,去掉only_full_group_by模式。

  1. 找到MySQL的配置文件my.cnf或者my.ini,这个文件默认在MySQL的安装目录的etc目录下。
  2. 找到[mysqld]标签所在的位置,增加如下配置。
[mysqld]
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
  1. 重启MySQL服务以生效。

2. 修改SQL语句

可以在SQL语句中进行调整,使其符合only_full_group_by模式中规定的限制条件。

正确的方式是确保GROUP BY子句包含了所有查询选择列表中的非聚合列,并不是所有的非聚合列都需要包含在GROUP BY子句里面。如果我们只想要非聚合列的唯一值,而不在意它们的值,那么可以使用聚合函数。

例如,原本的SQL语句是这样的:

SELECT col1, col2, col3
FROM tbl
WHERE some_col='some_val'
GROUP BY col1

only_full_group_by模式下,这条SQL语句会失败。我们可以调整SQL语句,使用MAX()函数或者MIN()函数,将GROUP BY子句中缺少的非聚合列从SELECT子句中删除并用聚合函数代替。

SELECT col1, MAX(col2), MAX(col3)
FROM tbl
WHERE some_col='some_val'
GROUP BY col1

如果需要全部保留非聚合列,则可以使用内联子查询或者临时表。

举例:

SELECT t1.*, t2.*
FROM (
    SELECT col1
    FROM tbl
    WHERE some_col='some_val'
    GROUP BY col1
) AS t1
JOIN tbl AS t2 ON t1.col1=t2.col1

示例说明

示例1

假设有这样一张表格t_student,其中包含学生ID、所属省份和所属城市三列数据。

CREATE TABLE t_student (
    id INT PRIMARY KEY,
    province VARCHAR(255) NOT NULL,
    city VARCHAR(255) NOT NULL
);

INSERT INTO t_student VALUES(1, 'Shandong', 'Jinan');
INSERT INTO t_student VALUES(2, 'Shandong', 'Qingdao');
INSERT INTO t_student VALUES(3, 'Jiangsu', 'Nanjing');
INSERT INTO t_student VALUES(4, 'Jiangsu', 'Suzhou');

如果我们想要获取每个省份中的任意一个城市,则可以使用如下的SQL语句:

SELECT id, province, city
FROM t_student
GROUP BY province;

在MySQL 5.7.9及以上的版本中,启用only_full_group_by时,会抛出如下异常:

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

为了解决这个问题,我们可在my.cnf或者my.ini中去掉only_full_group_by模式,或者修改SQL语句。具体来说,我们可以使用MAX()函数或者MIN()函数,将GROUP BY子句中缺少的非聚合列从SELECT子句中删除并用聚合函数代替。

-- 修改后的SQL语句
SELECT province, MAX(city)
FROM t_student
GROUP BY province;

示例2

假设有这样一张表格t_result,其中包含学生ID、考试类型和成绩三列数据。

CREATE TABLE t_result (
    id INT NOT NULL,
    type VARCHAR(255) NOT NULL,
    score FLOAT NOT NULL
);

INSERT INTO t_result VALUES (1, 'Math', 90);
INSERT INTO t_result VALUES (2, 'Math', 80);
INSERT INTO t_result VALUES (3, 'Chinese', 95);
INSERT INTO t_result VALUES (4, 'Chinese', 85);

如果我们想要获取每种考试类型中的最高分,则可以使用如下的SQL语句:

SELECT type, id, MAX(score)
FROM t_result
GROUP BY type;

在MySQL 5.7.9及以上的版本中,启用only_full_group_by时,会抛出如下异常:

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

为了解决这个问题,我们可在my.cnf或者my.ini中去掉only_full_group_by模式,或者修改SQL语句。具体来说,我们可以将缺少的非聚合列使用内联子查询或者临时表来获取。

-- 修改后的SQL语句,使用内联子查询
SELECT t1.type, t1.id, t1.score
FROM t_result t1
INNER JOIN (
    SELECT type, MAX(score) AS score
    FROM t_result
    GROUP BY type
) t2 ON t1.type=t2.type AND t1.score=t2.score;
-- 修改后的SQL语句,使用临时表
CREATE TEMPORARY TABLE t_max_score
    SELECT type, MAX(score) AS score
    FROM t_result
    GROUP BY type;

SELECT t1.type, t1.id, t1.score
FROM t_result t1
INNER JOIN t_max_score t2 ON t1.type=t2.type AND t1.score=t2.score;

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:解决MySQL 5.7.9版本sql_mode=only_full_group_by问题 - Python技术站

(0)
上一篇 2023年5月18日
下一篇 2023年5月18日

相关文章

  • MySQL使用二进制日志还原数据库

    MySQL 是一种开源的关系型数据库管理系统,它的日志文件是用于恢复和备份的重要部分。MySQL 支持三种类型的二进制日志,分别是:二进制日志、事务日志、和错误日志。其中,二进制日志是 MySQL 最常用的日志类型,它记录了所有添加、更改和删除表记录的 SQL 语句,是一个重要的恢复和备份工具。本文将详细介绍如何使用 MySQL 二进制日志还原数据库。 启用…

    MySQL 2023年3月10日
    00
  • java.sql.SQLException: No value specified for parameter 2 at com.mysql.jdbc.SQLError.create 小Bug异常

    public boolean updateMemberslnfo(MembersInfo membersInfo) throws SQLException{ StringBuffer sqlBuffer = new StringBuffer(“UPDATE membersinfo SET “); boolean check = true; List<O…

    MySQL 2023年4月12日
    00
  • GreatSQL社区月报 | 2023.03

    GreatSQL社区月报 | 2023.03 GreatSQL 是一个开源的 MySQL 技术路线数据库社区,社区致力于通过开放的社区合作,构建国内自主 MySQL 版本及开源数据库技术,推动中国开源数据库及应用生态繁荣发展。 为了帮助社区的小伙伴们更好地了解 GreatSQL 社区的实时进展,我们决定每月更新发布一次 GreatSQL 社区月报。月报的主要…

    MySQL 2023年4月17日
    00
  • Mysql使用索引实现查询优化

    MySQL 使用索引是优化查询效率的重要手段之一。索引是一种特殊的数据结构,可以帮助 MySQL 快速定位匹配的数据行。在本篇攻略中,我们将详细讲解如何使用索引实现查询优化。 索引介绍 索引是一种数据结构,可以帮助我们快速地定位匹配的数据记录。在 MySQL 中,常用的索引类型包括: B-Tree 索引:常用的索引类型,可以在 O(log n) 的时间内定位…

    MySQL 2023年5月19日
    00
  • MySQL GRANT:用户授权方法详解

    MySQL GRANT 命令是 MySQL 数据库中最重要的命令之一,用于授权用户相关数据库操作的权限。通过 GRANT 命令,可以实现对数据库对象(如数据库、数据表、视图等)的不同级别的访问控制和权限分配。 在 MySQL 中,我们可以使用 GRANT 命令将权限授予一个用户,这个用户可以是本地用户,也可以是远程用户。下面对 MySQL GRANT 命令进…

    MySQL 2023年3月10日
    00
  • MySQL explain 和 profiling 详解

    MySQL explain 和 profiling 详解 mysql explain MySQL 的 EXPLAIN 是一个用于查询优化的工具,它可以显示 MySQL 数据库如何执行查询。它返回一组关于查询执行计划的信息,包括用到的索引,表的连接顺序以及 MySQL 使用的查询类型。下面是 EXPLAIN 返回的列及其含义: id id:查询中每个 SELE…

    MySQL 2023年4月17日
    00
  • suse11安装mysql5.7

    下载地址http://mirrors.sohu.com/mysql/MySQL-5.7/ 1、     wget -c  http://mirrors.sohu.com/mysql/MySQL-5.7/MySQL-server-5.7.23-1.sles11.x86_64.rpm             wget -c  http://mirrors.soh…

    MySQL 2023年4月13日
    00
  • mysql查询学生表里面成绩第2名的学生成绩

    如图:    多表关联写法:    

    MySQL 2023年4月13日
    00
合作推广
合作推广
分享本页
返回顶部