在GROUP BY中选择了哪一行?

时间:2019-08-24 11:01:06

标签: mysql sql

假设我有一张桌子

+------+---------+--------+
| lang | title   | url    |
+------+---------+--------+
| pt   | Livro 1 | o294jl |
| en   | Book 1  | o294jl |
| en   | Book 2  | o294jl |
+------+---------+--------+

然后我运行查询

SELECT lang, title
FROM table
GROUP BY url

查询结果不是很明显,因为langtitle的值在组中是不同的。

SQL引擎如何选择要从组返回的行?在我的示例中必须选择哪一行?是在SQL标准中指定的吗?

2 个答案:

答案 0 :(得分:3)

从每个组的任意个匹配行中选择

个值。这些值可能来自不同的行以进行不同的运行。从理论上讲,同一SELECT中的不同列可以来自不同的行。

文档对此进行了解释:

  

如果禁用ONLY_FULL_GROUP_BY,则为标准的MySQL扩展   SQL对GROUP BY的使用允许选择列表,HAVING条件或   ORDER BY列表引用非聚集列,即使这些列   在功能上不依赖于GROUP BY列。 。 。 。 在这种情况下,服务器可以自由   从每个组中选择任何值,因此,除非它们相同,否则   选择的值是不确定的,这可能不是您所确定的   想要。

您应该阅读有关该主题的完整documentation

请注意,MySQL的默认行为是现在拒绝此类查询。是的!

答案 1 :(得分:1)

除了Gorden的答案外–实际上,引擎将只做最少的工作,即从组中找到的第一行中选择值。但是–第一行取决于执行计划,尤其取决于所选择的索引。

假设以下架构和数据:

#include <stdio.h>
#include <unistd.h>
int main() {
    char buf[100];
    fork();
    int n;
    while ((n = read(0, buf, sizeof buf)) > 0) {
        printf("%d: %*s\n", getpid(), n, buf);
    }
    return 0;
}

执行查询

CREATE TABLE test (
  `lang`  VARCHAR(2),
  `title` VARCHAR(50),
  `url`   VARCHAR(50)
) engine=InnoDB;

INSERT INTO test (`lang`, `title`, `url`) VALUES
  ('pt', 'Livro 1', 'o294jl'),
  ('en', 'Book 1', 'o294jl'),
  ('en', 'Book 2', 'o294jl');

返回

SELECT lang, title FROM test GROUP BY url;

这是插入顺序中的第一行(使用聚簇索引)。

如果我们现在在| lang | title | | ---- | ------- | | pt | Livro 1 | 上定义索引

(url, lang, title)

相同的SELECT查询返回

ALTER TABLE test ADD INDEX url_lang_title (url, lang, title);

这是新| lang | title | | ---- | ------ | | en | Book 1 | 索引中的第一行。

View on DB Fiddle

您将看到:具有完全相同的数据和完全相同的查询– MySQL可以返回不同的结果。而且,即使您不更改索引,也不能依赖所选的特定索引。引擎可以出于许多其他原因选择其他索引。

故事的寓意:不要问引擎会返回什么。而是通过编写确定性查询确切地告诉它您希望它返回什么。

相关问题