在 "ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'" 上询问原因?

Ask reason on "ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'"?

我知道这个限制和重写的替代方法SQL。但我想知道为什么?任何人都可以提供有关此限制的推论吗?

类似

的查询
select * from table where id in (select id from othertable)

基本上会被解释为

select * from table where exists 
   (select id from othertable where table.id = othertable.id)

这就是您对该查询的期望。您特别希望 IN 查询使用 othertable.id 上的索引。在manual中描述为

Some optimizations that MySQL itself makes are: [...]

  • MySQL rewrites IN, ALL, ANY, and SOME subqueries in an attempt to take advantage of the possibility that the select-list columns in the subquery are indexed.

如果您添加 limit:

,这并非纯属巧合,正是错误消息中提到的四个运算符
select * from table where id in 
   (select id from othertable order by id limit 10)

ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'.

不再可以直接以类似方式重写该查询,因为它不同于

select * from table where exists 
   (select id from othertable where table.id = othertable.id 
    order by id limit 10)

要执行带有限制的 IN,MySQL 可以检索 othertable 的前 10 行,将该结果集存储为 派生子 table 并检查 id 是否在其中。你当然可以这样做:

select * from table where id in 
   (select id from 
      (select id from othertable order by id limit 10) subtable)

类似于第一个示例,这将被解释为

select * from table where exists 
   (select * from 
      (select id from othertable order by id limit 10) subtable
    where table.id = subtable.id)

所以它混合了优化器的工作方式(它将重写查询)、limit 的工作方式(它在 找到 行后停止执行,而不是跳过它们)、期望的内容(索引的使用)以及开发人员最终是否决定允许特定语法。

您可能会争辩说,如果 MySQL 遇到带有 limit 子查询的 IN,它总是可以回退以作为派生 table 执行查询 - 但也可以你通过明确地使用派生的 subtable。您还可以争辩说您可以想办法实现它或以不同的方式实现它 - 你是对的,确实有。这就是错误消息中出现“yet”的原因。因此,请随意实施它们或至少描述它们,例如在功能请求中尽可能彻底地考虑 MySQL 的所有其他部分如何工作。但要确保它们实际上比仅使用 subtable.

更快