询问理由" ERROR 1235(42000):这个版本的MySQL还没有支持' LIMIT& IN / ALL / ANY / SOME子查询'"?

时间:2017-09-01 08:10:22

标签: mysql subquery limit

我知道这种限制以及重写SQL的替代方法。但我想知道原因?任何人都可以对此限制进行推断吗?

1 个答案:

答案 0 :(得分:2)

这样的查询
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中,它被描述为

  

MySQL本身做出的一些优化是:[...]

     
      
  • MySQL重写IN,ALL,ANY和SOME子查询,试图利用子查询中的select-list列被索引的可能性。
  •   

如果添加limit,这些不是纯粹的巧合,恰好是错误消息中提到的四个运算符:

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

ERROR 1235(42000):此版本的MySQL尚不支持'LIMIT& IN / ALL / ANY / SOME子查询'。

不再可能以类似的方式重写该查询,因为它与

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

要执行带有限制的IN,MySQL可以检索10个othertable的第一行,将该结果集存储为派生的子表并检查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遇到带有IN子查询的limit,MySQL总是可以回退以执行派生表 - 但你也可以明确地使用派生子表。您也可以争辩说,您可以考虑实施或以不同方式实施的方法 - 而且您是对的,有。这就是错误消息中有“ yet ”的原因。所以随意实施它们或至少描述它们,例如尽可能彻底地在功能请求中并考虑MySQL的所有其他部分如何工作。但要确保它们实际上比仅使用子表更快。