解决MySQL 5.7.9版本sql_mode=only_full_group_by问题

yizhihongxing

当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 8.0.13zip包安装方法

    下面是关于mysql 8.0.13zip包安装方法的完整攻略,分为以下几个步骤: 1. 下载mysql 8.0.13 zip包 首先需要下载mysql 8.0.13 zip包,可以从官网下载:https://dev.mysql.com/downloads/mysql/5.7.html#downloads,也可以从其他网站下载。下载完成后需要解压缩,将解压后的…

    MySQL 2023年5月18日
    00
  • 解决大于5.7版本mysql的分组报错Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated

    这个报错是由于MySQL 5.7版本以后对于分组查询的规则进行了更改导致的。现在要求分组查询中选择的列必须要么出现在GROUP BY子句中,要么是聚合函数,否则会报错。如果数据表中存在要查询的字段中有出现在GROUP BY子句中的列之外的字段时,就会出现“Expression #1 of SELECT list is not in GROUP BY clau…

    MySQL 2023年5月18日
    00
  • mysql乱码修改character_set_server

    [mac] 1、使用任何一个客户端或者命令行查询一下编码,俺用的是MySQLWorkbench SHOW VARIABLES LIKE ‘character_set_%’; 2、发现编码是character_set_server = Latin1 3、将编码改为UTF8 4、前往–>前往文件夹/usr/local/mysql/ 5、mysql-&gt…

    MySQL 2023年4月13日
    00
  • 重装MySQL最后一步失败的完美解决方案(经验总结)

    下面是“重装MySQL最后一步失败的完美解决方案(经验总结)”的详细攻略: 重装MySQL最后一步失败的完美解决方案(经验总结) 背景 当MySQL服务出现问题时,我们往往需要卸载掉原先的MySQL,并重装新的版本。但是,有时候在重装MySQL的过程中,可能会出现最后一步失败的情况,导致无法完成安装。这时候,我们需要采取一些措施来解决这个问题。 解决方案 步…

    MySQL 2023年5月18日
    00
  • 解析mysql 5.5字符集问题

    解析 MySQL 5.5 字符集问题的攻略包含以下步骤: 步骤一:确认 MySQL 5.5 字符集问题存在 在使用 MySQL 5.5 版本时,有时候会遇到字符集的问题,例如在插入中文到数据表中时,可能会出现乱码或者指定字符集无效等情况。因此,首先需要确认是否存在字符集问题。 可以通过以下命令来查看 MySQL 编码设置: show variables li…

    MySQL 2023年5月18日
    00
  • Mysql性能优化案例研究-覆盖索引和SQL_NO_CACHE

    下面是关于“Mysql性能优化案例研究-覆盖索引和SQL_NO_CACHE”的详细讲解攻略。 覆盖索引 什么是覆盖索引 覆盖索引是指一个查询中的字段都可以从索引中取得,无需回表查找。这种查询方法可以提高查询效率,减少回表查询的次数,从而提高了MySQL的查询性能。 如何使用覆盖索引 具体来说,使用覆盖索引需要注意以下几点: 索引要包含查询字段和需要的返回字段…

    MySQL 2023年5月19日
    00
  • 详解mysql慢日志查询

    详解MySQL慢日志查询 什么是MySQL慢日志 MySQL慢查询日志是MySQL服务器自带的一种日志记录功能,用于记录MySQL服务器中响应时间超过预设阈值的SQL语句。MySQL慢查询日志功能对于优化查询语句、解决SQL语句性能问题非常有帮助。 如何启用MySQL慢日志 在MySQL服务器的配置文件中(一般为/etc/my.cnf或/etc/mysql/…

    MySQL 2023年5月19日
    00
  • MySQL无法启动几种常见问题小结

    下面是MySQL无法启动常见问题小结的完整攻略: 问题一:端口被占用 如果MySQL无法启动,最常见的问题是端口被占用。通常情况下,MySQL默认使用3306端口,如果这个端口已经被占用(比如另外一个MySQL实例正在使用该端口),那么MySQL就无法启动。解决这个问题的方法有以下几种: 方法一:修改MySQL使用的端口号 可以通过修改mysqld.cnf配…

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