解决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 2023年5月19日
    00
  • windows上安装mysql5.7

    安装前准备: 系统:windows7-x64 MySql:mysql5.7.19-X64-windows压缩包 安装步骤: 在windows上安装mysql有两种方式,一种是安装mysql压缩包,一种是图形化的安装,只要是配置好my.ini配置文件,压缩包安装比图形化更快更简单。这篇文章主要说明mysql压缩包的安装步骤。 一、新建数据库文件存放目录 将my…

    MySQL 2023年4月12日
    00
  • 基于mysql多实例安装的深入解析

    基于mysql多实例安装的深入解析 为什么需要多实例? 在一台服务器上启动多个mysql实例的主要原因是:需要在同一台服务器上运行多个不同版本的mysql,并希望它们可以同时运行。另一个原因是,我们可能需要启动不同的mysql实例,以在不同的端口号上监听TCP连接,从而应对不同的应用场景。 安装前的准备 在开始多实例安装之前,我们需要进行以下准备工作: 1.…

    MySQL 2023年5月18日
    00
  • 优化InnoDB表BLOB,TEXT列的存储效率

    优化InnoDB表BLOB、TEXT列的存储效率,可以根据以下几方面进行优化。 1. 调整InnoDB表的行格式 InnoDB存储引擎提供了4种行格式,分别为:Redundant、Compact、Dynamic、Compressed。其中,Redundant和Compact格式已经被淘汰,因为它们不能存储BLOB、TEXT等大数据类型。而Dynamic和Co…

    MySQL 2023年5月19日
    00
  • 分析MySQL抛出异常的几种常见解决方式

    分析MySQL抛出异常的几种常见解决方式 MySQL 是一种常用的数据库管理系统,但在使用 MySQL 时也会遇到一些常见的异常情况。以下是解决这些异常情况的几种方法: 1. 处理连接超时异常 连接超时是一种非常常见的异常情况。当使用 MySQL 连接时,如果在指定的时间内没有接收到响应,则会抛出连接超时异常。处理连接超时异常的一种方法是在连接时使用 con…

    MySQL 2023年5月18日
    00
  • MySQL创建索引(CREATE INDEX)方法详解

    MySQL创建索引可以提高查询效率并减少查询的时间和资源消耗。以下是MySQL创建索引的方法和实例说明。 语法: CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX 索引名 ON 表名(列名1,列名2,….); 其中,UNIQUE表示唯一性索引,FULLTEXT表示全文索引,SPATIAL表示空间索引。 示例: (1)创建普通索…

    MySQL 2023年3月10日
    00
  • mysql 超大数据/表管理技巧

    MySQL 超大数据/表管理技巧攻略 在处理超大数据和表的时候,我们需要注意以下几个方面的技巧: 分区表技术 垂直切分和水平切分技术 使用 NoSQL 数据库 使用存储引擎 下面我们来详细介绍这些技巧。 1. 分区表技术 分区表技术是指将一张大表按照一定规则分割成多个小表,使得查询和维护都更加高效。常用的分区策略有范围分区、哈希分区和列表分区。 范围分区是指…

    MySQL 2023年5月19日
    00
  • Mysql数据库的QPS和TPS的意义和计算方法

    MySQL数据库的QPS和TPS是数据库性能评估的两个重要指标,QPS代表每秒查询率,而TPS代表每秒事务处理率。 QPS的计算公式为:Query数/时间,例如,如果在1秒钟内执行了1000次查询,则QPS为1000。QPS可以用来评估系统的查询性能。 TPS的计算方法有三种,分别是Commit、Rollback以及Insert+Update+Delete。…

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