提问人:Dhanu K 提问时间:1/27/2017 最后编辑:CowDhanu K 更新时间:9/24/2023 访问量:874817
SELECT 列表不在 GROUP BY 子句中,并且包含非聚合列 ....与sql_mode=only_full_group_by不兼容
SELECT list is not in GROUP BY clause and contains nonaggregated column .... incompatible with sql_mode=only_full_group_by
问:
我在带有 WAMP Server 的 Windows PC 上使用 MySQL 5.7.13。
我的问题是在执行此查询时
SELECT *
FROM `tbl_customer_pod_uploads`
WHERE `load_id` = '78' AND
`status` = 'Active'
GROUP BY `proof_type`
我总是遇到这样的错误。
SELECT 列表的表达式 #1 不在 GROUP BY 子句中,并且包含非聚合列“returntr_prod.tbl_customer_pod_uploads.id”,该列在功能上不依赖于 GROUP BY 子句中的列;这与 sql_mode=only_full_group_by 不兼容
你能告诉我最好的解决方案吗?
我的结果应该如下:
+----+---------+---------+---------+----------+-----------+------------+---------------+--------------+------------+--------+---------------------+---------------------+
| id | user_id | load_id | bill_id | latitude | langitude | proof_type | document_type | file_name | is_private | status | createdon | updatedon |
+----+---------+---------+---------+----------+-----------+------------+---------------+--------------+------------+--------+---------------------+---------------------+
| 1 | 1 | 78 | 1 | 21.1212 | 21.5454 | 1 | 1 | id_Card.docx | 0 | Active | 2017-01-27 11:30:11 | 2017-01-27 11:30:14 |
+----+---------+---------+---------+----------+-----------+------------+---------------+--------------+------------+--------+---------------------+---------------------+
答:
当MySQL的模式打开时,这意味着在使用时将应用严格的ANSI SQL规则。关于您的查询,这意味着如果您是该列,那么您只能选择两件事:only_full_group_by
GROUP BY
GROUP BY
proof_type
- 列,或者
proof_type
- 任何其他列的聚合
通过其他列的“聚合”,我的意思是使用聚合函数,例如 , , 或与另一列一起使用。因此,在您的情况下,以下查询是有效的:MIN()
MAX()
AVG()
SELECT proof_type,
MAX(id) AS max_id,
MAX(some_col),
MIN(some_other_col)
FROM tbl_customer_pod_uploads
WHERE load_id = '78' AND
status = 'Active'
GROUP BY proof_type
我在 SO 上看到的绝大多数 MySQL 问题都关闭了严格模式,因此查询正在运行,但结果不正确。在您的情况下,查询根本不会运行,迫使您考虑您真正想要做什么。GROUP BY
注意:ANSI SQL 通过还包括在功能上依赖于所选列的列来扩展允许选择的内容。函数依赖关系的一个示例是按表中的主键列进行分组。由于主键保证对于每条记录都是唯一的,因此还将确定任何其他列的值。MySQL是允许这样做的数据库之一(SQL Server和Oracle不AFAIK)。GROUP BY
评论
GROUP BY
这
SELECT 列表的表达式 #1 不在 GROUP BY 子句中,并且包含非聚合列“returntr_prod.tbl_customer_pod_uploads.id”,该列在功能上不依赖于 GROUP BY 子句中的列;这与 sql_mode=only_full_group_by 不兼容
将通过此命令更改MySQL中的sql模式即可解决。
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
这也对我有用。 我使用了这个,因为在我的项目中有很多这样的查询,所以我只是将 sql 模式更改为 only_full_group_by。
或者,只需在 SELECT 语句指定的 GROUP BY 子句中包含所有列。sql_mode可以保持启用状态。
谢谢。:-)
更新日期:14 Jul 2023
更改 SQL 模式是一种解决方案,但是,结构化查询语言的最佳实践仍然是避免选择所有 (SELECT * ...) 列,而是在分组列上使用聚合器函数,如 @Tim Biegeleisen 在下面提到的答案 https://stackoverflow.com/a/41887524/3602846
评论
您可以通过某些命令禁用 sql_mode=only_full_group_by,您可以通过终端或 MySql IDE 尝试此操作
mysql> set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
mysql> set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
打开WAMP面板并打开MySQL配置文件。在其中搜索“sql_mode”,如果找到它,请将其设置为“”,否则,如果找不到,请将sql_mode=“”添加到文件中。
重新启动MySQL服务器,您就可以开始了...
祝您编码愉快。
要使查询在 SQL92 中合法,必须在选择列表中省略 name 列或在 GROUP BY 子句中命名。
SQL99 和更高版本允许每个可选功能部件 T301 使用此类非聚合,如果它们在功能上依赖于 GROUP BY 列:如果 name 和 custid 之间存在这种关系,则查询是合法的。例如,如果客户是客户的主要密钥,情况就是如此。
MySQL 5.7.5 及更高版本实现了功能依赖性检测。如果启用了 ONLY_FULL_GROUP_BY SQL 模式(默认情况下),MySQL 会拒绝选择列表、HAVING 条件或 ORDER BY 列表引用非聚合列的查询,这些列既未在 GROUP BY 子句中命名,也不在功能上依赖于它们。
via MySQL :: MySQL 5.7 参考手册 :: 12.19.3 MySQL对GROUP BY的处理
您可以通过以下命令更改 sql 模式来解决它:
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
和。。。请记住重新连接数据库!!
从外观上看,我认为按多个列/字段分组不会损害您的结果。你为什么不尝试像这样添加到组中:
GROUP BY `proof_type`, `id`
这将首先分组,然后。我希望这不会改变结果。在某些/大多数情况下,按多列分组会产生错误的结果。proof_type
id
MySql引擎中ONLY_FULL_GROUP_BY
有一个系统变量。
从 Mysql 版本 5.7.5 开始:默认情况下启用 SQL 模式ONLY_FULL_GROUP_BY
在版本 5.7.5 之前:默认情况下未启用。ONLY_FULL_GROUP_BY
如果启用了 SQL 模式(默认情况下从版本 5.7.5 开始),MySQL 会拒绝选择列表、条件或列表引用非聚合列的查询,这些列既未在子句中命名,也不在功能上依赖于它们。ONLY_FULL_GROUP_BY
HAVING
ORDER BY
GROUP BY
要解决问题,请使用以下任何一种解决方案(以下 3 种)
(1) PHPMyAdmin
禁用:模式ONLY_FULL_GROUP_BY
如果您使用的是phpMyAdmin,请更改sql_mode
设置,如下图所示。
编辑变量并从值中删除文本sql mode
ONLY_FULL_GROUP_BY
或
(2) SQL/命令提示符
通过运行以下命令禁用:模式。ONLY_FULL_GROUP_BY
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
或
(3) 不要使用 SELECT *
不要禁用该模式,但ONLY_FULL_GROUP_BY
在查询中使用相关列。related 表示列,它们要么位于子句中,要么带有聚合函数(、、等)的列SELECT
group by
MAX
MIN
SUM
COUNT
重要提示
使用所做的更改不会永久设置它,并且每次重新启动后都会恢复。point(1) OR point(2)
因此,您应该在配置文件中设置它(例如 ),以便更改在MySQL重新启动后仍然有效:/etc/mysql/my.cnf
[mysqld]
配置文件:/etc/mysql/my.cnf
变量名称:ORsql_mode
sql-mode
从值中删除单词ONLY_FULL_GROUP_BY
并保存文件。
注意:如果您在配置文件中没有找到变量,请在文件末尾插入以下 2 行sql_mode
[mysqld]
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
评论
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
这对我来说很好用。
在你的 中,写下这个:my.ini
[mysqld]
sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
取决于您的版本。艺术
[mysqld]
sql_mode = ""
或者干脆删除它:ONLY_FULL_GROUP_BY
评论
- 登录phpMyAdmin
- 导航到:服务器:localhost:3306,然后执行 不选择任何数据库
- 单击顶部菜单中的变量
- 搜索“sql mode”并将相应的值编辑为:NO_ENGINE_SUBSTITUTION
就这样。
我在我的 Ec2 中做到了这一点,它就像魅力一样。
以下方法解决了我的问题:
在 ubuntu 中
类型:sudo vi /etc/mysql/my.cnf
键入 A 进入插入模式
在最后一行中,粘贴下面两行代码:
[mysqld]
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
键入 esc 退出输入模式
Type :wq to save and close vim.
键入以重新启动 MySQL。sudo service mysql restart
评论
MySQL 8.0 更新
您将没有,因为它已被删除,如此处所述 - how-to-set-sql-mode-in-my-cnf-in-mysql-8sql-mode
NO_AUTO_CREATE_USER
[mysqld]
sql-mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
此外,如果有人没有文件,那么他们可以创建一个新文件,然后添加上面的行。my.cnf
/etc/mysql/my.cnf
在 Ubuntu 中
步骤1:
sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
第 2 步:转到最后一行并添加以下内容
sql_mode = ""
第 3 步:保存
第 4 步:重新启动 mysql 服务器。
嗨,不要使用所有列,而是使用 .它运行良好。只需检查即可。ANY_VALUE(column_name)
例如:
SELECT proof_type,any_value("customer_name") as customer_name
FROM `tbl_customer_pod_uploads`
WHERE `load_id` = '78' AND `status` = 'Active' GROUP BY `proof_type`
评论
如果您使用的是 PhpMyAdmin,请搜索“SQL 模式”并删除值:,刚刚做了,没问题。ONLY_FULL_GROUP_BY
转到 phpMyAdmin 并打开控制台并执行此请求
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
> sudo nano /etc/mysql/my.cnf
在下面输入
[mysqld]
sql_mode = ""
Ctrl + O => Y = Ctrl + X
> sudo service mysql restart
这是一种非常快速和简单的永久设置方法
注意:运行是临时的,在服务器重新启动时,您仍然会出现错误。
要永久修复此问题,请执行以下操作SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
- 以 root 身份登录您的服务器
- 在终端运行
wget https://gist.githubusercontent.com/nfourtythree/90fb8ef5eeafdf478f522720314c60bd/raw/disable-strict-mode.sh
- 通过运行
chmod +x disable-strict-mode.sh
- 通过运行
./disable-strict-mode.sh
完成后,将对mysql进行更改并重新启动
我的部分数据库粉碎也遇到了类似的问题。我所做的是通过PHPStorm数据库控制台更改了数据库中的参数,如下所示:
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
现在像魅力一样工作
only_full_group_by = on 告诉 MySQL 引擎:当您不确定要显示什么结果并抛出错误时,不要应用。只有在明确告诉您该怎么做时才应用它,即当它充满和完美时!GROUP BY
Group By
Group By
only_full_group_by = off 告诉 MySQL 引擎:始终应用,如果您不确定要选择什么结果,请随机选择一个!GROUP BY
如果您正确使用 GROUP BY
,则不必将其关闭!
例:
表:用户
id | name
----------------
1 ali
2 john
3 ali
当您在列上使用时:GROUP BY
name
SELECT * FROM users GROUP BY name;
有两种可能的结果:
1 ali
2 john
或
2 john
3 ali
MYSQL不知道该选择什么结果!因为有不同的 s,但都有 .id
name=ali
解决方案 1:
仅选择字段:name
SELECT name FROM users GROUP BY name;
结果:
ali
john
这是一个完美的解决方案。删除使人感到困惑的列。这意味着您知道自己在做什么。通常,您不需要
这些列,但如果需要它们,请转到“解决方法 3”。(不是解决方案 2!GROUP BY
解决方案 2:
关闭 .MYSQL将随机选择两种可能的结果之一!!(如果你真的不在乎它会选择什么,也没关系,但记得在查询后立即打开它,以防止将来的 groupBys 出现意外行为)only_full_group_by
id
解决方案 3
使用像 这样的函数来帮助 MYSQL 决定它必须选择什么。Aggregate
MIN()
MAX()
例如:
SELECT MAX(id), name FROM users GROUP BY name;
它将选择具有最大 id 的行:ali
2 john
3 ali
旁注:请注意,MySQL并不关心表中有哪些数据。查询本身是模棱两可的。因此,例如,表中甚至可能没有记录,但仍然会看到only_full_group_by错误。
评论
我遇到了这个问题,以下查询还不够
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
因为我使用的是存储过程。执行此查询后,我不得不放弃该过程并重新创建。
在运行之前,请查询运行以下查询
SET SQL_MODE = '';
评论
对于在本地使用 CentOS/RHEL(Linux 服务器)和 XAMPP 的用户
您好,我找到了一个非常不同的解决方案,我希望这对 somone 有所帮助。(可能看起来矫枉过正,但这确实对我有用,不像其他解决方案)
我正在运行 CentOS 7,我的所有代码都在本地工作,但是当我将其上传到我的服务器时,我开始收到此问题解决的错误。
几个小时后,我尝试从不同的角度查看问题,我记得我的本地设置使用 XAMPP,我以为我使用的是 MySQL 8(MySQL 8 安装在我的服务器上)。
但是从XAMPP登录MySql后,我得到了下一个输出:
mysql -u root -p //Login
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 27
Server version: 10.4.18-MariaDB mariadb.org binary distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
是的,您可能已经注意到了,XAMPP使用MariaDB,因此解决方案是卸载mysql并安装MariaDB
当我运行 Centos 7 时,执行此操作的步骤如下:
- 从服务器中删除 mysql
# yum remove mysql mysql-server
- 更新您的系统(每次我们安装新东西时,这都很常见)
# sudo yum -y update
- 将 MariaDB 添加到存储库
# sudo tee /etc/yum.repos.d/MariaDB.repo<<EOF
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.4/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
EOF
- 更新缓存
# sudo yum makecache fast
- 安装 MariaDB
# sudo yum -y install MariaDB-server MariaDB-client
- 将 MariaDB 添加到启动(每次系统重新启动时启动 MariaDB)
#sudo systemctl enable --now mariadb
然后,您可以通过运行以下命令来保护安装:
# sudo mysql_secure_installation
最后一个命令将开始一个过程,您可以在其中设置密码和其他选项。
之后,不要忘记添加非root用户并授予其必要的权限,这是因为您不能在应用程序中使用root用户(是的,我稍后必须弄清楚)
首次使用 root 帐户登录:
# mysql -u root -p
然后添加您的用户并授予权限:
CREATE USER 'YourUserName'@localhost IDENTIFIED BY 'YourPassword';
GRANT ALL PRIVILEGES ON *.* TO 'YourUserName'@localhost IDENTIFIED BY 'YourPassword' WITH GRANT OPTION;
最后,您必须创建数据库,导入表/数据/触发器/过程。
现在,您将能够毫无问题地运行您的代码,就像您的本地设置一样。(也许你必须安装mysql扩展,以防你也必须在本地进行)。
您也可以简单地将 GROUP_CONCAT() 添加到非聚合列中。
喜欢GROUP_CONCAT(your_column)
登录phpMyAdmin
导航到 : 服务器: http://localhost/phpmyadmin,不要选择任何数据库
单击顶部菜单中的 SQL,并在代码下方害虫 在服务器上运行 SQL 查询/查询 Sorce 链接SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
两种解决方案:
a) 使用
设置全局 sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
b) 通过使用 ANY_VALUE() 引用非聚合列,可以在不禁用ONLY_FULL_GROUP_BY的情况下实现相同的效果。
ANY_VALUE(值)
评论
如果您在 Mac 上使用 MAMP,则在重新启动 MAMP 时,将对 MySQL 中变量所做的任何更改都将被删除。要确保更改是永久性的,请执行以下操作:
停止正在运行的 MAMP 服务器。
使用文本编辑器创建名为 my.cnf 的文件,并将其保存到 /Applications/MAMP/conf 文件夹。将文件放在文件夹的根目录下(这似乎有点奇怪,因为它包含大量 apache 文件夹,但没关系)。将以下行添加到文件中:
[mysqld]
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
保存文件并关闭编辑器。 启动 MAMP 服务器。
这将使更改永久化。
就我而言,这是我的旧sql_mode
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
show variables like "sql_mode";
然后我把它设置为这个
SET sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
步骤 1。检查sql模式:
SELECT @@GLOBAL.sql_mode;
第2步。在 /etc/mysql/conf.d/ 目录下创建一个新的配置文件:
sudo nano /etc/mysql/conf.d/disable_strict_mode.cnf
在编辑器中输入以下文本:
[mysqld]
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
第 3 步。重启MySQL:
sudo service mysql restart
第 4 步。确认更改:
SELECT @@GLOBAL.sql_mode;
如果您不想禁用模式,则只需在 GROUP BY 子句中指定要选择的每个列。ONLY_FULL_GROUP_BY
不要使用通配符 (*),并确保您的列与您的需求相关
有时你只需要检查你的查询是否有正确的顺序和排序方式。
GROUP BY pp.id_product
FIELD(pp.id_product, 1600, 1870, 2300 );
在将排序的方向 ( 或 ) 添加到查询之前,这不会运行。DESC
ASC
GROUP BY pp.id_product
FIELD(pp.id_product, 1600, 1870, 2300 ) DESC;
这也可以在不弄乱服务器的会话和全局设置的情况下解决问题。
设置全局sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
如果问题仍然存在并且您正在使用 Laravel,请在 config/database.php 中将 'strict' 设置为 false
'mysql' => [ ... 'strict' => false, ... ],
SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''))
下一个:多对多重复
评论
SELECT *
only_full_group_by
tbl_customer_pod_uploads
load_id
status
proof_type