我使用此查询创建一个表:
create table a (
`id` int not null auto_increment,
b varchar(10),
primary key (`id`)
);
执行
select distinct `id` from a order by `b`;
导致此错误:
ERROR 3065(HY000):ORDER BY子句的表达式#1不在SELECT列表中,引用列'portal.a.b'不在SELECT列表中;这与DISTINCT不兼容
但是,如果我将查询更改为
select `id` from a group by `id` order by `b`;
它在逻辑上是等价的,它成功了。
我正在使用official Docker image for MySQL和mysql --version
显示器
mysql Ver 8.0.12 for x86_64上的Linux(MySQL社区服务器 - GPL)
似乎MySQL仍然没有在选择不同的查询中检测功能依赖性。我对吗? MySQL的开发人员是否会解决这个问题?
相反的行为实际上报告为一个bug和fixed in MySQL 5.7.5:
与ONLY_FULL_GROUP_BY SQL模式相关的几个问题已得到纠正:
- 启用ONLY_FULL_GROUP_BY后,如果访问的表被视图替换,则会拒绝某些有效查询。
- SELECT DISTINCT col1 ... ORDER BY col2形式的查询符合SQL2003禁用(隐藏的ORDER BY列与DISTINCT结合),但在启用ONLY_FULL_GROUP_BY SQL模式时未被拒绝。
此外,documentation明确指出这是预期的行为:
若要防止此问题,如果任何ORDER BY表达式不满足以下条件中的至少一个,则具有DISTINCT和ORDER BY的查询将被拒绝为无效:
- 表达式在选择列表中等于1
- 表达式引用并属于查询所选表的所有列都是选择列表的元素
没有提到功能依赖。与group by
相反,相关的错误消息也没有引用功能依赖性。
虽然sql标准中的可选功能T301功能依赖性确实修改了group by
(和其他)的一致性规则,但它不会改变对order by
加上distinct
的任何限制,这意味着它仍然是被禁止的。
这来自MySQL 5.7中引入的新SQL模式:ONLY_FULL_GROUP_BY
此模式的目标是使MySQL在GROUP BY查询中表现为SQL标准。
在您的数据库上激活此模式。您可以禁用它,或调整您的查询以遵守标准,这可能是最好的事情。
这会抛出你的错误:
SET sql_mode = 'ONLY_FULL_GROUP_BY';
drop table a;
create table a (
`id` int not null auto_increment,
b varchar(10),
primary key (`id`)
);
INSERT INTO a VALUES (NULL, 'aaaa');
INSERT INTO a VALUES (NULL, 'bbbb');
select distinct `id` from a order by `b`;
如果删除ONLY_FULL_GROUP_BY模式,则会得到结果:
SET sql_mode = '';
drop table a;
create table a (
`id` int not null auto_increment,
b varchar(10),
primary key (`id`)
);
INSERT INTO a VALUES (NULL, 'aaaa');
INSERT INTO a VALUES (NULL, 'bbbb');
select distinct `id` from a order by `b`;
你可以在Rextester上看到它