假设我有一张桌子
+------+---------+--------+
| lang | title | url |
+------+---------+--------+
| pt | Livro 1 | o294jl |
| en | Book 1 | o294jl |
| en | Book 2 | o294jl |
+------+---------+--------+
然后我运行查询
SELECT lang, title
FROM table
GROUP BY url
查询结果不是很明显,因为lang
和title
的值在组中是不同的。
SQL引擎如何选择要从组返回的行?在我的示例中必须选择哪一行?是在SQL标准中指定的吗?
答案 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 |
索引中的第一行。
您将看到:具有完全相同的数据和完全相同的查询– MySQL可以返回不同的结果。而且,即使您不更改索引,也不能依赖所选的特定索引。引擎可以出于许多其他原因选择其他索引。
故事的寓意:不要问引擎会返回什么。而是通过编写确定性查询确切地告诉它您希望它返回什么。