MySQL GROUP BY行为

Mat*_*hew 15 mysql sql group-by

鉴于下表' foo'

ID | First Name | Last Name
----------------------------
67   John        Smith
----------------------------
67   Bill        Jacobs
Run Code Online (Sandbox Code Playgroud)

什么first_namelast_name将下面的查询返回,为什么?

SELECT * FROM foo WHERE ID = 67 GROUP BY ID
Run Code Online (Sandbox Code Playgroud)

Bil*_*win 27

MySQL任意选择一行.在实践中,常用的MySQL存储引擎相对于物理存储返回组中第一行的值.

create table foo (id serial primary key, category varchar(10));

insert into foo (category) values 
  ('foo'), ('foo'), ('foo'), ('bar'), ('bar'), ('bar');

select * from foo group by category;

+----+----------+
| id | category |
+----+----------+
|  4 | bar      |
|  1 | foo      |
+----+----------+
Run Code Online (Sandbox Code Playgroud)

其他人都认为MySQL允许您运行此查询,即使它具有任意且可能具有误导性的结果.SQL标准和大多数其他RDBMS供应商不允许这种模糊的GROUP BY查询.这就是所谓的单值规则:在选择列表中的所有列必须在GROUP BY标准明确一部分,否则内部的聚合函数,例如COUNT(),MAX()等等.

MySQL支持一种SQL模式ONLY_FULL_GROUP_BY,如果您尝试运行违反SQL标准语义的查询,则会使MySQL返回错误.

AFAIK,SQLite是唯一允许分组查询中含糊不清的列的其他RDBMS.SQLite返回组中最后一行的值:

select * from foo group by category;

6|bar
3|foo
Run Code Online (Sandbox Code Playgroud)

我们可以想象查询不会模糊,但仍然违反SQL标准语义.

SELECT foo.*, parent_of_foo.* 
FROM foo JOIN parent_of_foo 
  ON (foo.parent_id = parent_of_foo.parent_id) 
GROUP BY foo_id;
Run Code Online (Sandbox Code Playgroud)

没有合理的方法可以产生模棱两可的结果.如果我们GROUP BY foo的主键,foo中的每一行都有自己的组.所以来自foo的任何列只能在组中有一个值.如果组由foo的主键定义,即使加入foo中外键引用的另一个表,每个组也只能有一个值.

MySQL和SQLite相信您可以设计逻辑上明确的查询.形式上,select-list中的每一列必须是GROUP BY条件中列的函数依赖项.如果你不遵守这个,那就是你的错.:-)

标准SQL更加严格,不允许一些的查询可能是明确的-可能是因为它会过于复杂的RDBMS以确保一般.

  • 你应该获得这个答案的诺贝尔奖. (3认同)

Sab*_*lik 5

MySQL 的分组依据与标准 SQL 行为不一致,MySQL 使获取其他列变得很容易,但同时你永远无法确定你会得到哪一列。

更新:参考此页面: http://dev.mysql.com/doc/refman/5.0/en/group-by-handling.html

使用此功能时,每个组中的所有行对于从 GROUP BY 部分省略的列应具有相同的值。服务器可以自由地从组中返回任何值,因此结果是不确定的,除非所有值都相同。


Cha*_*les 0

很可能会选择第二(最后)行的名字和姓氏。

您可以添加 ORDER BY 子句来提示您希望如何对分组的行进行排序。

  • 不,MySQL 从组中的第一行返回值。ORDER BY 在组形成后应用于行——它根本不影响组内行的顺序。 (2认同)