MySQL: vista con subconsulta en la limitación de la cláusula FROM
-
03-07-2019 - |
Pregunta
En MySQL 5.0, ¿por qué ocurre el siguiente error al intentar crear una vista con una subconsulta en la cláusula FROM?
ERROR 1349 (HY000): SELECT de View contiene una subconsulta en la cláusula FROM
Si esta es una limitación del motor MySQL, ¿por qué no han implementado esta función todavía?
Además, ¿cuáles son algunas buenas soluciones para esta limitación?
¿Existen soluciones alternativas que funcionen para cualquier subconsulta en la cláusula FROM o hay algunas consultas que no se pueden expresar sin usar una subconsulta en la cláusula FROM?
Una consulta de ejemplo (se enterró en un comentario):
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
Solución
No se pudo escribir la consulta en tu comentario como:
SELECT u1.name as UserName from Message m1, User u1
WHERE u1.uid = m1.UserFromID GROUP BY u1.name HAVING count(m1.UserFromId)>3
Eso también debería ayudar con los problemas de velocidad conocidos con las subconsultas en MySQL
Otros consejos
Tuve el mismo problema. Quería crear una vista para mostrar información del año más reciente, a partir de una tabla con registros de 2009 a 2011. Aquí está la consulta original:
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
Esquema de la solución:
- crear una vista para cada subconsulta
- reemplazar las subconsultas con esas vistas
Aquí está la consulta de la solución:
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;
Funciona bien en mysql 5.0.45, sin mucha penalización de velocidad (en comparación con la ejecución la selección original de la subconsulta sin ninguna vista).
Parece ser un problema conocido.
http://dev.mysql.com/doc/ refman / 5.1 / es / unnamed-views.html
http://bugs.mysql.com/bug.php?id=16757
Muchas consultas IN se pueden volver a escribir como uniones (izquierda externa) y un IS (NO) NULL de algún tipo. por ejemplo
SELECT * FROM FOO WHERE ID IN (SELECT ID FROM FOO2)
se puede reescribir como
SELECT FOO.* FROM FOO JOIN FOO2 ON FOO.ID=FOO2.ID
o
SELECT * FROM FOO WHERE ID NOT IN (SELECT ID FROM FOO2)
puede ser
SELECT FOO.* FROM FOO
LEFT OUTER JOIN FOO2
ON FOO.ID=FOO2.ID WHERE FOO.ID IS NULL
crear una vista para cada subconsulta es el camino a seguir. Lo tengo funcionando como un encanto.
Puedes solucionar esto creando una VISTA por separado para cualquier subconsulta que quieras usar y luego unirte a ella en la VISTA que estás creando. Aquí hay un ejemplo: http://blog.gruffdavies.com/2015/01/25/a-neat-mysql-hack-to-create-a-view-with-subquery-in-the-from-clause/
Esto es bastante útil ya que probablemente querrás reutilizarlo de todos modos y te ayuda a mantener tu SQL DRY.