MySQL: Affichage avec sous-requête dans la clause FROM Clause Limitation

Dans MySQL 5.0, pourquoi l’erreur suivante se produit-elle lorsque vous essayez de créer une vue avec une sous-requête dans la clause FROM?

ERROR 1349 (HY000): SELECT de View contient une sous-requête dans la clause FROM

S’il s’agit d’une limitation du moteur MySQL, pourquoi n’ont-ils pas encore implémenté cette fonctionnalité?

En outre, quelles sont les bonnes solutions de contournement pour cette limitation?

Existe-t-il des solutions de contournement qui fonctionnent pour toute sous-requête dans la clause FROM ou existe-t-il des requêtes qui ne peuvent pas être exprimées sans utiliser une sous-requête dans la clause FROM?


Un exemple de requête (a été enterré dans un commentaire):

SELECT temp.UserName FROM (SELECT u1.name as UserName, COUNT(m1.UserFromId) as SentCount FROM Message m1, User u1 WHERE u1.uid = m1.UserFromId Group BY u1.name HAVING SentCount > 3 ) as temp 

La requête de votre commentaire ne pourrait-elle pas être écrite comme suit:

 SELECT u1.name as UserName from Message m1, User u1 WHERE u1.uid = m1.UserFromID GROUP BY u1.name HAVING count(m1.UserFromId)>3 

Cela devrait également aider avec les problèmes de vitesse connus avec les sous-requêtes dans MySQL

J’ai eu le même problème. Je voulais créer une vue pour afficher les informations de l’année la plus récente, à partir d’une table avec des enregistrements de 2009 à 2011. Voici la requête d’origine:

 SELECT a.* FROM a JOIN ( SELECT a.alias, MAX(a.year) as max_year FROM a GROUP BY a.alias ) b ON a.alias=b.alias and a.year=b.max_year 

Aperçu de la solution:

  1. créer une vue pour chaque sous-requête
  2. remplacer les sous-requêtes par ces vues

Voici la requête de solution:

 CREATE VIEW v_max_year AS SELECT alias, MAX(year) as max_year FROM a GROUP BY a.alias; CREATE VIEW v_latest_info AS SELECT a.* FROM a JOIN v_max_year b ON a.alias=b.alias and a.year=b.max_year; 

Cela fonctionne très bien sur mysql 5.0.45, sans trop de pénalité de vitesse (par rapport à l’exécution de la sélection de sous-requête d’origine sans aucune vue).

Cela semble être un problème connu.

http://dev.mysql.com/doc/refman/5.1/en/unnamed-views.html

http://bugs.mysql.com/bug.php?id=16757

De nombreuses requêtes IN peuvent être réécrites sous la forme de jointures (externes) et d’un IS (NOT) NULL. par exemple

 SELECT * FROM FOO WHERE ID IN (SELECT ID FROM FOO2) 

peut être réécrit comme

 SELECT FOO.* FROM FOO JOIN FOO2 ON FOO.ID=FOO2.ID 

ou

 SELECT * FROM FOO WHERE ID NOT IN (SELECT ID FROM FOO2) 

peut être

 SELECT FOO.* FROM FOO LEFT OUTER JOIN FOO2 ON FOO.ID=FOO2.ID WHERE FOO.ID IS NULL 

créer une vue pour chaque sous-requête est la voie à suivre. Je l’ai fait fonctionner comme un charme.

Vous pouvez contourner ce problème en créant une vue distincte pour toutes les sous-requêtes que vous souhaitez utiliser, puis joignez-la à celle que vous créez. Voici un exemple: http://blog.gruffdavies.com/2015/01/25/a-neat-mysql-hack-to-create-a-view-with-subquery-in-the-from-clause/

C’est très pratique car vous voudrez probablement le réutiliser quand même et vous aider à conserver votre code SQL DRY.