Je connais cette restriction et l'alternative à réécrire SQL. Mais je me demande pourquoi? Quelqu'un peut-il fournir une inférence sur cette restriction?Demander raison sur "ERROR 1235 (42000): Cette version de MySQL ne supporte pas encore 'LIMIT & IN/ALL/ANY/SOME sous-requête'"?
Répondre
Une requête comme
select * from table where id in (select id from othertable)
sera essentiellement interprété comme
select * from table where exists
(select id from othertable where table.id = othertable.id)
C'est ce que vous attendez pour cette requête. Vous vous attendez en particulier à la requête IN
pour utiliser l'index sur othertable.id
. Dans le manual, il est décrit comme
Quelques optimisations MySQL lui-même sont par exemple: [...]
- MySQL récrit EN, TOUT, TOUT, et quelques sous-requêtes pour tenter de tirer profit de la possibilité que les colonnes select-list de la sous-requête soient indexées.
Ce sont, non pas par pure coïncidence, exactement les quatre opérateurs mentionnés dans le message d'erreur si vous ajoutez un limit
:
select * from table where id in
(select id from othertable order by id limit 10)
erreur 1235 (42000): Cette version de MySQL ne supporte pas encore 'LIMIT & IN/ALL/ANY/QUEL sous-requête'.
Réécriture cette requête de manière similaire est pas directement plus possible, car il est quelque chose de différent que
select * from table where exists
(select id from othertable where table.id = othertable.id
order by id limit 10)
Pour exécuter le IN
avec une limite, MySQL pourrait récupérer les 10 premières lignes de othertable
, stocker ce resultset comme sous-table dérivée et vérifiez si l'id est là. Et vous pouvez bien sûr faire exactement cela:
select * from table where id in
(select id from
(select id from othertable order by id limit 10) subtable)
Cette volonté, par analogie avec le premier exemple, être interprété comme
select * from table where exists
(select * from
(select id from othertable order by id limit 10) subtable
where table.id = subtable.id)
Il est donc un mélange de la façon dont les travaux d'optimisation (il réécrira la requête), comment fonctionne limit
(il arrête l'exécution après trouver lignes, ne pas les ignorer), ce qui est attendu (l'utilisation d'index) et finalement si les développeurs ont décidé d'autoriser une syntaxe spécifique ou non.
Vous pourriez argumenter que MySQL pourrait toujours se replier pour exécuter la requête en tant que table dérivée s'il rencontre IN
avec une sous-requête limit
- mais vous pourriez aussi en utilisant explicitement une sous-table dérivée. Vous pourriez également soutenir que vous pouvez penser à des façons de mettre en œuvre ou de mettre en œuvre cela différemment - et vous avez raison, il y en a. C'est pourquoi il y a un "encore" dans le message d'erreur. Alors n'hésitez pas à les mettre en œuvre ou au moins les décrire par exemple. dans une demande de fonctionnalité aussi complètement que possible et en considération de la façon dont toutes les autres parties de MySQL fonctionnent. Mais assurez-vous qu'ils sont en fait plus rapides que l'utilisation d'une sous-table.