MySQL: visualizza con subquery nella limitazione della clausola FROM
-
03-07-2019 - |
Domanda
In MySQL 5.0 perché si verifica il seguente errore quando si tenta di creare una vista con una subquery nella clausola FROM?
ERRORE 1349 (HY000): SELECT di View contiene una sottoquery nella clausola FROM
Se questa è una limitazione del motore MySQL, perché non hanno ancora implementato questa funzione?
Inoltre, quali sono alcune buone soluzioni per questa limitazione?
Esistono soluzioni alternative che funzionano per qualsiasi subquery nella clausola FROM o esistono query che non possono essere espresse senza utilizzare una subquery nella clausola FROM?
Una query di esempio (è stata sepolta in un commento):
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
Soluzione
La query nel tuo commento non può essere scritta semplicemente come:
SELECT u1.name as UserName from Message m1, User u1
WHERE u1.uid = m1.UserFromID GROUP BY u1.name HAVING count(m1.UserFromId)>3
Ciò dovrebbe anche aiutare con i problemi di velocità noti con le subquery in MySQL
Altri suggerimenti
Ho avuto lo stesso problema. Volevo creare una vista per mostrare le informazioni dell'anno più recente, da una tabella con record dal 2009 al 2011. Ecco la query originale:
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
Schema della soluzione:
- crea una vista per ogni subquery
- sostituisci le sottoquery con quelle viste
Ecco la query della soluzione:
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;
Funziona benissimo su mysql 5.0.45, senza troppe penalità di velocità (rispetto all'esecuzione la sottoquery originale seleziona senza alcuna vista).
Sembra essere un problema noto.
http://dev.mysql.com/doc/ refman / 5.1 / it / senza nome-views.html
http://bugs.mysql.com/bug.php?id=16757
Molte query IN possono essere riscritte come join (esterni a sinistra) e un IS (NOT) NULL di qualche tipo. per esempio
SELECT * FROM FOO WHERE ID IN (SELECT ID FROM FOO2)
può essere riscritto come
SELECT FOO.* FROM FOO JOIN FOO2 ON FOO.ID=FOO2.ID
o
SELECT * FROM FOO WHERE ID NOT IN (SELECT ID FROM FOO2)
può essere
SELECT FOO.* FROM FOO
LEFT OUTER JOIN FOO2
ON FOO.ID=FOO2.ID WHERE FOO.ID IS NULL
creare una vista per ogni sottoquery è la strada da percorrere. Ha funzionato come un fascino.
Puoi aggirare il problema creando una VISTA separata per qualsiasi subquery che desideri utilizzare e poi unisciti a quella nella VISTA che stai creando. Ecco un esempio: http://blog.gruffdavies.com/2015/01/25/a-neat-mysql-hack-to-create-a-view-with-subquery-in-the-from-clause/
Questo è abbastanza utile poiché molto probabilmente vorrai riutilizzarlo comunque e ti aiuta a mantenere il tuo SQL DRY.