MySQL 是否通过允许选择不属于 group by 子句的列来打破标准?

Pau*_*ite 11 mysql group-by sql-standard

我习惯了包括 SQL Server 在内的 Microsoft 技术。今天我遇到了一个问答,其中引用了 MySQL 文档中的以下段落:

标准 SQL会拒绝您的查询,因为您不能在聚合查询中选择不属于 GROUP BY 子句的非聚合字段。MySQL 扩展了 GROUP BY 的使用,以便选择列表可以引用未在 GROUP BY 子句中命名的非聚合列。这意味着前面的查询在 MySQL 中是合法的。您可以使用此功能通过避免不必要的列排序和分组来获得更好的性能。但是,这主要在未在 GROUP BY 中命名的每个非聚合列中的所有值对于每个组都相同时很有用。服务器可以自由地从每个组中选择任何值,因此除非它们相同,否则选择的值是 不确定的

MySQL允许这样做是否违反了标准?如何?允许这样做的结果是什么?

在此处输入图片说明

Pau*_*ite 9

标准SQL会拒绝你的查询,因为你无法选择非集合字段不是该组的一部分BY子句在聚合查询

这是正确的,直到 1992 年

但从2003 年及以后,显然错误的。

来自 SQL-2003 标准,6IWD6-02-Foundation-2011-01.pdf,来自 http://www.wiscorp.com/,第 7.12 段(查询规范),第 398 页

  1. 如果 T 是一个分组表,那么让 G 是 T 的分组列的集合。即函数依赖G上在聚合参数包含一个的((设定功能说明书)),其聚合的查询是QS

现在MYSQL,通过允许实现此功能不仅是列函数依赖于分组列,但允许所有列。这给不了解分组工作原理的用户带来了一些问题,并在他们不期望的地方得到不确定的结果。

但是您说 MySQL 添加了一个与 SQL 标准冲突的功能是正确的(尽管您似乎认为这是错误的原因)。它并不完全准确,因为他们添加了 SQL 标准功能,但不是以最好的方式(更像是简单的方式),但它确实与最新标准相冲突。

为了回答您的问题,我认为此 MySQL 功能(扩展)的原因是符合最新的 SQL 标准(2003+)。为什么他们选择以这种方式实现它(不完全兼容),我们只能推测。

正如@Quassnoi 和@Johan 通过示例回答的那样,这主要是性能和可维护性问题。但是不能轻易地将 RDBMS 更改为足够聪明(天网除外)来识别功能相关的列,因此 MySQL 开发人员做出了选择:

我们 (MySQL) 为您(MySQL 用户)提供 SQL-2003 标准中的此功能。它提高了某些GROUP BY查询的速度,但有一个问题。您必须小心(而不是 SQL 引擎),因此SELECTHAVING列表中的列在功能上依赖于这些GROUP BY列。否则,您可能会得到不确定的结果。

如果你想禁用它,你可以设置sql_modeONLY_FULL_GROUP_BY

这一切都在MySQL 文档中:Extensions to GROUP BY(5.5) - 虽然不在上面的措辞中,但在你的引用中(他们甚至忘记提到它与标准 SQL-2003 的偏差而不是标准的 SQL-92)。我认为这种选择在所有软件中都很常见,包括其他 RDBMS。它们是出于性能、向后兼容性和许多其他原因而设计的。'' is the same as NULL例如,Oracle 有著名的,SQL-Server 也可能有一些。

还有这篇由 Peter Bouman撰写的博客文章,其中为 MySQL 开发人员的选择辩护:Debunking GROUP BY myths

2011 年,正如@Mark Byers在评论中(在 DBA.SE 的一个相关问题中)告诉我们的那样,PostgreSQL 9.1 添加了一个专为此目的而设计的新功能(发布日期:2011 年 9 月)。它比 MySQL 的实现更严格,更接近标准。

后来,在 2015 年 MySQL 宣布在 5.7 版本中,行为得到改进以符合标准并实际识别函数依赖项,(甚至比 Postgres 实现更好)。文档:MySQL 处理GROUP BY(5.7)和 Peter Bouman 的另一篇博文:MySQL 5.7.5:GROUP BY尊重函数依赖!

原作者