我已经升级了我的系统,并为我正在开发的web应用程序安装了MySql 5.7.9和php。我有一个查询,是动态创建的,当运行在旧版本的MySQL它工作得很好。自从升级到5.7,我得到这个错误:

SELECT列表的表达式#1不在GROUP BY子句中,并且包含 未聚合列的support_desk.mod_users_groups。Group_id '就是 在功能上不依赖于GROUP BY子句中的列;这是 sql_mode=only_full_group_by不兼容

请注意Mysql 5.7的手册页中关于Server SQL Modes的主题。

这个问题让我很困扰:

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选项,或者还有其他需要做的事情?


当前回答

进入mysql或phpmyadmin,选择数据库 然后简单地执行这个查询,它就可以工作了。 它对我来说很好。

SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

其他回答

可以为group_id添加唯一索引;如果您确定group_id是唯一的。

它可以在不修改查询的情况下解决您的问题。

迟来的回答,但在回答中还没有提到。也许它应该完善现有的已经很全面的答案。至少,当我不得不分割一个包含太多字段的表时,它确实解决了我的问题。

我会试着解释这个错误是关于什么的。 从MySQL 5.7.5开始,选项ONLY_FULL_GROUP_BY默认启用。 因此,根据标准SQL92和更早的版本:

不允许查询select列表,HAVING条件, 或ORDER BY列表引用既没有命名也没有聚合的列 在GROUP BY子句中也不依赖于(唯一的 按列分组

(在文档中阅读更多)

举个例子:

SELECT * FROM `users` GROUP BY `name`;

执行上述查询后,您将得到错误消息。

#1055 - SELECT列表的表达式#1不在GROUP BY子句中,并且包含非聚合列的testsite.user。我不是 函数依赖于GROUP BY子句中的列;这是 sql_mode=only_full_group_by不兼容

为什么? 因为MySQL不能确切地理解,从分组记录中检索哪些特定值,这就是问题所在。

例如,假设你在用户表中有这样的记录:

您将执行上面显示的无效查询。 你会得到如上所示的错误,因为,有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不确切地知道要检索分组记录的值,并且通过使用这个函数,您要求它获取其中任何一个(在本例中,获取了name = John的第一条记录的电子邮件)。 确切地说,我想不出你为什么想要这种行为存在。 如果你不明白我的意思,请阅读更多关于如何在MySQL中分组工作,这是非常简单的。

最后,这里有一个更简单但有效的查询。 如果希望根据可用年龄查询用户总数,可能需要写下这个查询

SELECT `age`, COUNT(`age`) FROM `users` GROUP BY `age`;

根据MySQL规则,这是完全有效的。 等等。 重要的是要了解问题到底是什么,然后才写下解决方案。

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.重新启动MySQL服务器。

mysql.server restart

这有助于我理解整个问题:

https://stackoverflow.com/a/20074634/1066234 https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

下面是另一个问题查询的例子。

问题:

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(*) as attempts, SUM(elapsed) as elapsedtotal,用户id,时间戳,questionid, answerid, SUM(correct) as correct, elapsed, ipaddress FROM gameplay WHERE时间戳>= DATE_SUB(NOW(),间隔1天) AND userid = 1

在本例中,表达式#4在GROUP BY中缺失。

如果您不想在当前查询中进行任何更改,那么请遵循以下步骤-

流浪汉SSH进你的盒子 类型: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。