MySQL: Afficher avec sous-requête dans la limitation de la clause FROM
-
03-07-2019 - |
Question
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?
ERREUR 1349 (HY000): Le SELECT de la vue contient une sous-requête dans la clause FROM
S'il s'agit d'une limitation du moteur MySQL, pourquoi n'a-t-il 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 n'importe quelle 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 solution
La requête dans votre commentaire ne peut pas simplement être écrite ainsi:
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 à résoudre les problèmes de vitesse connus liés aux sous-requêtes dans MySQL
Autres conseils
J'ai eu le même problème. Je souhaitais créer une vue pour afficher les informations de l'année la plus récente, à partir d'un tableau contenant 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:
- créer une vue pour chaque sous-requête
- 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é liée à la vitesse (comparé à l'exécution la sous-requête d'origine sélectionne sans aucune vue).
Cela semble être un problème connu.
http://dev.mysql.com/doc/ refman / 5.1 / fr / unnamed-views.html
http://bugs.mysql.com/bug.php?id=16757
De nombreuses requêtes IN peuvent être réécrites sous forme de jointures (externe gauche) et d'une sorte 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 eu comme un charme.
Vous pouvez contourner ce problème en créant une vue distincte pour chaque sous-requête que vous souhaitez utiliser, puis rejoignez-la dans la vue 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 aidera à garder votre code SQL au sec.