我已经升级了我的系统并安装了MySql 5.7.9和php,用于我正在处理的Web应用程序。我有一个动态创建的查询,当在旧版本的MySql中运行时,它可以正常工作。自升级到5.7后,我收到此错误:
SELECT列表的表达式#1不在GROUP BY子句中并且包含 nonaggregated列'support_desk.mod_users_groups.group_id'是 在功能上不依赖于GROUP BY子句中的列;这是 与sql_mode = only_full_group_by
不兼容
请注意主题为Server SQL Modes的Mysql 5.7的手册页。
这是给我带来麻烦的查询:
SELECT mod_users_groups.group_id AS 'value',
group_name AS 'text'
FROM mod_users_groups
LEFT JOIN mod_users_data ON mod_users_groups.group_id = mod_users_data.group_id
WHERE mod_users_groups.active = 1
AND mod_users_groups.department_id = 1
AND mod_users_groups.manage_work_orders = 1
AND group_name != 'root'
AND group_name != 'superuser'
GROUP BY group_name
HAVING COUNT(`user_id`) > 0
ORDER BY group_name
我在这个问题上做了一些谷歌搜索,但我不明白only_full_group_by
足以弄清楚我需要做些什么来修复查询。我可以关闭only_full_group_by
选项,还是还有其他我需要做的事情?
如果您需要更多信息,请与我们联系。
答案 0 :(得分:293)
您可以尝试通过执行以下操作来禁用only_full_group_by
设置:
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';
MySQL 8不接受NO_AUTO_CREATE_USER
,因此需要删除。
答案 1 :(得分:286)
我只想将group_id
添加到GROUP BY
。
当SELECT
不属于GROUP BY
的列时,组中的该列可能有多个值,但结果中只有一个值的空间。因此,需要告知数据库通常如何将这些多个值组合成一个值。通常,这是通过聚合函数完成的,例如COUNT()
,SUM()
,MAX()
等...我说通常是因为大多数其他流行的数据库系统坚持这个。但是,在版本5.7之前的MySQL中,默认行为更宽容,因为它不会抱怨,然后随意选择任何值!它还有一个ANY_VALUE()
函数,如果你真的需要和以前一样的行为,它可以用作这个问题的另一个解决方案。这种灵活性是有代价的,因为它是非确定性的,所以除非你有充分的理由需要它,否则我不推荐它。 MySQL现在默认启用only_full_group_by
设置是有充分理由的,因此最好习惯它并使您的查询符合它。
那么为什么我的上述简单答案呢?我做了几个假设:
1)group_id
是唯一的。看似合理,这是一个ID'毕竟。
2)group_name
也是唯一的。这可能不是一个合理的假设。如果情况并非如此,并且您有一些重复group_names
,然后您按照我的建议将group_id
添加到GROUP BY
,您可能会发现现在获得的结果比之前更多,因为现在,具有相同名称的组在结果中将具有单独的行。对我来说,这比隐藏这些重复组更好,因为数据库已经悄悄选择了一个值!
当涉及多个表时,使用表名或别名对所有列进行限定也是一种很好的做法...
SELECT
g.group_id AS 'value',
g.group_name AS 'text'
FROM mod_users_groups g
LEFT JOIN mod_users_data d ON g.group_id = d.group_id
WHERE g.active = 1
AND g.department_id = 1
AND g.manage_work_orders = 1
AND g.group_name != 'root'
AND g.group_name != 'superuser'
GROUP BY
g.group_name,
g.group_id
HAVING COUNT(d.user_id) > 0
ORDER BY g.group_name
答案 2 :(得分:278)
您可以按照其他答案中的说明关闭警告消息,或者您可以理解正在发生的事情并进行修复。
As of MySQL 5.7.5, the default SQL mode includes ONLY_FULL_GROUP_BY这意味着当您对行进行分组然后从这些组中选择某些内容时,您需要明确说明应该从哪个行进行选择。
Mysql需要知道您要查找的组中的哪一行,这为您提供了两个选项
group by rect.color, rect.value
中,这可能是您想要的,但在某些情况下会返回您可能不需要的相同颜色的重复结果AVG()
MIN()
MAX()
complete list等组内寻找的行ANY_VALUE()
。 doc 答案 3 :(得分:153)
如果您不想对当前查询进行任何更改,请按照以下步骤进行操作 -
sudo vim /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
退出输入模式
:wq
以保存并关闭vim。sudo service mysql restart
以重新启动MySQL。答案 4 :(得分:46)
使用ANY_VALUE()
来引用非聚合列。
您可以在不停用
ONLY_FULL_GROUP_BY
的情况下达到相同的效果 使用ANY_VALUE()
来引用非聚合列。...
启用
ONLY_FULL_GROUP_BY
时此查询可能无效,因为选择列表中的非聚合地址列未在GROUP BY
子句中命名:SELECT name, address, MAX(age) FROM t GROUP BY name;
...
如果您知道,对于给定的数据集,每个名称值实际上唯一地确定地址值,则地址在功能上实际上取决于名称。要告诉MySQL接受查询,可以使用
ANY_VALUE()
函数:SELECT name, ANY_VALUE(address), MAX(age) FROM t GROUP BY name;
答案 5 :(得分:41)
我会试着解释一下这个错误是什么
从MySQL 5.7.5开始,默认情况下启用选项ONLY_FULL_GROUP_BY
因此,根据标准SQL92及更早版本:
不允许查询选择列表,HAVING条件, 或ORDER BY列表引用既未命名的非聚合列 在GROUP BY子句中,也不是在功能上依赖于(唯一的) 由GROUP BY列确定
所以,例如:
SELECT * FROM `users` GROUP BY `name`;
执行上述查询后,您将收到错误消息。
#1055 - SELECT列表的表达式#1不在GROUP BY子句中,并且包含非聚合列'testsite.user.id',它不是 功能上依赖于GROUP BY子句中的列;这是 与sql_mode = only_full_group_by
不兼容
为什么?
因为MySQL不完全理解,从分组记录中检索哪些特定值,这就是重点。
您将在上面执行无效查询showen
并且您将收到上面显示的错误,因为有3条名称为John
的记录,这很好,但是,它们都有不同的email
字段值。
因此,MySQL根本不了解它们中的哪一个返回到结果分组记录中。
您可以通过简单地更改您的查询来解决此问题:
SELECT `name` FROM `users` GROUP BY `name`
另外,你可能想要在SELECT部分添加更多字段,但你不能这样做,如果它们没有聚合,但你可以使用拐点(但非常不推荐):
SELECT ANY_VALUE(`id`), ANY_VALUE(`email`), `name` FROM `users` GROUP BY `name`
现在,您可能会问,为什么强烈建议不要使用ANY_VALUE
?
因为MySQL并不确切知道要检索的分组记录的值,并且通过使用此函数,您要求它获取它们中的任何一个(在这种情况下,获取名称= John的第一条记录的电子邮件)。
我无法想出你为什么要这种行为存在的想法。
如果你不了解我,请阅读更多关于如何在MySQL中进行分组的工作,这很简单。
最后,这是一个更简单但有效的查询 如果您想根据可用年龄查询总用户数,您可能需要记下此查询
SELECT `age`, COUNT(`age`) FROM `users` GROUP BY `age`;
根据MySQL规则,这完全有效。
等等。
重要的是要了解问题到底是什么,然后写下解决方案。
答案 6 :(得分:35)
我在Laravel宅基地上使用Laravel 5.3,mysql 5.7.12(我相信0.5.0)
即使明确设置编辑storage/public
以反映:
com/google/guava
我仍然收到错误。
我必须将/etc/mysql/my.cnf
从[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
更改为config/database.php
:
true
进一步阅读:
https://laracasts.com/discuss/channels/servers/set-set-sql-mode-on-homestead https://mattstauffer.co/blog/strict-mode-and-other-mysql-customizations-in-laravel-5-2
答案 7 :(得分:18)
如果您正在使用wamp 3.0.6或除稳定版2.5之外的任何高级版本,您可能会遇到此问题,首先问题是sql。你必须相应地命名字段。但还有另一种方法可以解决它。点击wamp的绿色图标。 mysql-> mysql settings-> sql_mode->没有。或者从控制台,您可以更改默认值。
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';
答案 8 :(得分:13)
在文件中添加行(如下所述):/ etc / mysql / my.cnf
[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
对我来说很好。 服务器版本:5.7.18-0ubuntu0.16.04.1 - (Ubuntu)
答案 9 :(得分:9)
对于mac:
1.将默认的my-default.cnf复制到/etc/my.cnf
sudo cp $(brew --prefix mysql)/support-files/my-default.cnf /etc/my.cnf
2.使用您喜欢的编辑器在my.cnf中更改sql_mode并将其设置为
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
3.Restart MySQL服务器。
mysql.server restart
答案 10 :(得分:6)
对于localhost / wampserver 3,我们可以设置sql-mode = user_mode来删除此错误:
click on wamp icon -> MySql -> MySql Setting -> sql-mode -> user_mode
然后重启wamp或apache
答案 11 :(得分:6)
转到mysql或phpmyadmin并选择数据库 然后只需执行此查询即可。 对我来说很好。
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
答案 12 :(得分:4)
这有助于我理解整个问题:
以下是另一个有问题的查询示例。
<强>有问题的:强>
SELECT COUNT(*) as attempts, SUM(elapsed) as elapsedtotal, userid, timestamp, questionid, answerid, SUM(correct) as correct, elapsed, ipaddress FROM `gameplay`
WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 1 DAY)
AND cookieid = #
通过将此添加到最后解决:
GROUP BY timestamp, userid, cookieid, questionid, answerid, elapsed, ipaddress
注意:请参阅PHP中的错误消息,它会告诉您问题所在。
示例:
MySQL查询错误1140:在没有GROUP BY的聚合查询中,SELECT列表的表达式#4包含非聚合列'db.gameplay.timestamp';这与sql_mode = only_full_group_by不兼容 - 查询:SELECT COUNT(*)作为尝试,SUM(已用)为elapsedtotal,userid,timestamp,questionid,answerid,SUM(正确)为正确,已过去,ipaddress FROM gameplay 时间戳&gt; = DATE_SUB(NOW(),INTERVAL 1天) AND userid = 1
在这种情况下,GROUP BY中缺少表达式#4 。
答案 13 :(得分:2)
如果您使用 doctrine查询构建器与 Symfony 发生此错误,并且此错误是由 orderBy 引起的:
注意select
您想要的列groupBy
,并使用addGroupBy
代替groupBy
:
$query = $this->createQueryBuilder('smth')->addGroupBy('smth.mycolumn');
适用于 Symfony3 -
答案 14 :(得分:2)
您可以向unique index
添加group_id
;如果您确定group_id
是唯一的。
它可以在不修改查询的情况下解决您的问题。
答案较晚,但答案中尚未提及。也许它应该完成已经全面的答案。至少它确实解决了我的情况,当我不得不拆分一个包含太多字段的表时。
答案 15 :(得分:0)
上面的共识答案是好的,但是如果在修复my.cnf文件后在存储过程中运行查询时遇到问题,请尝试再次加载SP。
我怀疑MySQL必须已经使用最初设置的默认only_full_group_by来编译SP。因此,即使当我更改my.cnf并重新启动mysqld时,它对SP也不起作用,并且它们始终失败,并显示“ SELECT列表不在GROUP BY子句中,并且包含未聚合的列... ...在功能上不依赖于GROUP中的列BY子句;与sql_mode = only_full_group_by“不兼容。
重新加载SP必须导致现在重新编译它们,并且禁用了only_full_group_by。之后,它们似乎按预期工作。
答案 16 :(得分:0)
我必须在Ubuntu 18.04上编辑以下文件:
/etc/mysql/mysql.conf.d/mysqld.cnf
使用
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
和
sudo service mysql restart
答案 17 :(得分:0)
不使用您的确切SQL的道歉
我使用此查询来克服Mysql警告。
SELECT count(*) AS cnt, `regions_id`
FROM regionables
WHERE `regionable_id` = '115' OR `regionable_id` = '714'
GROUP BY `regions_id`
HAVING cnt > 1
请注意我的关键
count(*) AS cnt