【问题标题】:MySQL : isn't in GROUP BYMySQL:不在 GROUP BY 中
【发布时间】:2014-11-06 04:01:44
【问题描述】:

该站点产生结果,但使用 SELECT COUNT 和 SELECT 查询,使用 GROUP BY 有两个不同的结果计数。这可能是由于 phpmyadmin 中显示但站点上没有显示的错误。

查询:

SELECT count(DISTINCT `name`) as `numrows` FROM `users` WHERE `verified` = '1'

SELECT `name`, `type`, `language`, `code` FROM `users` WHERE `verified` = '1' GROUP BY `name` ORDER BY `count` DESC LIMIT 0, 25

PhpMyAdmin 提供以下错误:

1055 - 'main.users.type' 不在 GROUP BY 中

阅读 MySQL 文档时,我仍然不清楚我必须修复什么。我似乎无法理解这一点。

【问题讨论】:

  • 第一个查询是按名称进行隐式分组。第二个,写一个类似的方式是这样的: SELECT name FROM users WHERE verified = '1' GROUP BY name ORDER BY COUNT(*) DESC LIMIT 0, 25
  • 我不确定你在暗示什么。使用查询: SELECT name,type,language FROM synset WHERE verify = '1' GROUP BY name ORDER BY COUNT() DESC LIMIT 0, 25 会发生同样的错误。类型不在 Group By 如果我添加类型和语言,错误就会消失。这可能是由于升级到 MySql 造成的吗? SELECT name,type,language FROM synset WHERE verify = '1' GROUP BY name,type,language ORDER BY COUNT() DESC LIMIT 0, 25 可以正常工作。
  • 显然,将所有字段添加到 group by 时查询时间很糟糕
  • 嗨@James - SELECT 或 ORDER BY 子句中使用的任何列/表达式如果没有被聚合(COUNT、SUM 等),则必须包含在 GROUP BY 子句中。这就是您收到错误的原因 - 您选择了列类型、语言和代码,但它们不在 GROUP BY 子句中(如接受的答案所示)。如果 MySQL 中有设置自动分组,我个人会非常谨慎地使用它。
  • @JordanParker: "如果 MySQL 中有设置自动分组" - 这实际上是默认行为。 James 显然启用了ONLY_FULL_GROUP_BY 选项。否则该语句将只返回“随机”结果(MySQL 不称其为随机,他们称其为“不确定”)percona.com/blog/2006/09/06/…

标签: mysql sql phpmyadmin mysql-error-1055


【解决方案1】:

你需要有一个完整的组:

SELECT `name`, `type`, `language`, `code` 
FROM `users` 
WHERE `verified` = '1' 
GROUP BY `name`, `type`, `language`, `code` 
ORDER BY `count` DESC LIMIT 0, 25

SQL92 要求 select 子句中的所有列(聚合除外)都是 group by 子句的一部分。 SQL99 稍微放宽了这个限制,并声明 select 子句中的所有列都必须在功能上依赖于 group by 子句。 MySQL 默认允许部分分组,这可能会产生不确定的答案,例如:

create table t (x int, y int);
insert into t (x,y) values (1,1),(1,2),(1,3);
select x,y from t group by x;
+------+------+
| x    | y    |
+------+------+
|    1 |    1 |
+------+------+

即为组 x 选择一个随机 y。可以通过设置@@sql_mode 来防止这种行为:

set @@sql_mode='ONLY_FULL_GROUP_BY';
select x,y from t group by x; 
ERROR 1055 (42000): 'test.t.y' isn't in GROUP BY

【讨论】:

  • 我只是在阅读 ONLY_FULL_GROUP_BY :) 这个组需要所有列的问题是查询的速度。但是 - 这是正确的答案。可以设置sql_mode,在我的情况下我不需要阻止这种行为。在其他情况下,这很值得了解和遵循。
  • 很好的答案和很好的部分分组示例有很大帮助!非常感谢!
  • 这是一个与 OP 的查询截然不同的查询。添加所有列是解决歧义组的核心选项。
  • @Caleth,你有什么建议,向选择列表中的每一列添加一个随机聚合函数而不是分组依据的一部分?
  • 不是“随机”聚合,而是适当聚合。 @O。琼斯有一个很好的建议。
【解决方案2】:

这个问题的最佳解决方案当然是使用完整的GROUP BY 表达式。

但是还有另一个解决方案可以解决 ONLY_FULL_GROUP_BY 将旧 MySQL 扩展阻止到 GROUP BY 的问题。

SELECT name, 
       ANY_VALUE(type) type,
       ANY_VALUE(language) language,
       ANY_VALUE(code) code 
  FROM users  
 WHERE verified = '1' 
 GROUP BY name 
 ORDER BY count DESC LIMIT 0, 25

ANY_VALUE() 明确声明了过去在 MySQL 不完整的 GROUP BY 操作中隐含的内容——服务器可以选择任何返回值。

【讨论】:

  • 谢谢,也为我工作!如果有人希望使用所有选项来处理该错误,那么它们是:dev.mysql.com/doc/refman/5.7/en/…
  • 这有效,但仅在您真正知道 ANY_VALUE 列具有相同值时才使用,因此它可以轻松捕获一个值,并且在与 GROUP BY 一起使用时您会得到正确的结果,并且您确实知道只有 GROUP BY 列必须具体。
  • 这确实比上述所有解决方案都更有帮助。我在共享主机 cPanel 上并且无法更改 sql_mode,我不得不寻找不会弄乱我的查询的解决方法。这样,您就可以保留查询,只需添加 ANYVALUE(cellname) cellname 就可以了。
【解决方案3】:

上面多次提到的另一个解决方案是关闭烦人的 'ONLY_FULL_GROUP_BY',例如就像在这篇文章中一样: Disable ONLY_FULL_GROUP_BY

如果您不想在多个小时内重构整个项目,我认为此解决方案非常有用。如果您不关心不是 GROUP BY 列表的列的不可预测值。

【讨论】:

  • 禁用 ONLY_FULL_GROUP_BY 会强制 MySQL 接受无效的 SQL GROUP BY 查询。因此,values it returns for the columns that are not in the GROUP BY clause are indeterminate.这意味着查询可以并且被允许使用相同的输入数据返回不同的结果。
  • @axiac 当然我已经考虑到了,GROP BY 语句中未提及的列将返回一些不可预测的值。如果我需要例如按地标分组且不关心 id 的条目,比禁用 ONLY_FULL_GROUP_BY 可能是最合理的。例如。如果您有一个旧版 ORM,它会自动将该 id 附加到 SELECT 中,无论您是否想要它。所以我会很高兴,如果我的答案是 0。
【解决方案4】:

只需禁用查询的严格性。

【讨论】:

    【解决方案5】:

    首先要看看为什么会这样。早期版本允许我们稍有疏忽:虽然分组列的值在结果中完全列出(每个列一个没有例外),但其他选定列的值或多或少被省略 - 但代码可以't(不想)代表你告诉哪些人:

    - Hey, MYSQL, list the families of the street - but add a first name as well to every row.
    - Okay sir, but shall I use the father's or the mother's or...? I'm a machine, give exact orders!
    

    现在我们了解了原因,我们可以决定是否对其他列有偏好。使用

    MAX() AS
    MIN() AS
    etc, works with strings, too
    

    或者如果它真的都一样,例如与分组值相关的非聚合值之间没有区别,请使用

    ANY_VALUE() AS
    

    无论哪种方式,您都让 mysql 知道您知道自己“模棱两可”,但您真的不想专注于除您分组的列之外的所有列。

    【讨论】:

      猜你喜欢
      • 2020-06-30
      • 2011-07-18
      • 1970-01-01
      • 2021-01-09
      • 2013-01-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多