MySQL:Просмотр с подзапросом в ограничении предложения FROM
-
03-07-2019 - |
Вопрос
Почему в MySQL 5.0 возникает следующая ошибка при попытке создать представление с подзапросом в предложении FROM?
ОШИБКА 1349 (HY000):SELECT представления содержит подзапрос в предложении FROM.
Если это ограничение движка MySQL, то почему они до сих пор не реализовали эту возможность?
Кроме того, каковы хорошие способы обхода этого ограничения?
Существуют ли какие-либо обходные пути, которые работают для любого подзапроса в предложении FROM, или есть ли некоторые запросы, которые невозможно выразить без использования подзапроса в предложении FROM?
Пример запроса (был скрыт в комментарии):
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
Решение
Нельзя ли запрос в вашем комментарии записать так:
SELECT u1.name as UserName from Message m1, User u1
WHERE u1.uid = m1.UserFromID GROUP BY u1.name HAVING count(m1.UserFromId)>3
Это также должно помочь решить известные проблемы со скоростью подзапросов в MySQL.
Другие советы
У меня такая же проблема.Я хотел создать представление для отображения информации за последний год из таблицы с записями с 2009 по 2011 год.Вот исходный запрос:
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
Схема решения:
- создать представление для каждого подзапроса
- замените подзапросы этими представлениями
Вот запрос решения:
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;
Он отлично работает на MySQL 5.0.45, без большого штрафа на скорость (по сравнению с выполнением исходного Sub-Query Select без каких-либо представлений).
Похоже, это известная проблема.
http://dev.mysql.com/doc/refman/5.1/en/unnamed-views.html
http://bugs.mysql.com/bug.php?id=16757
Многие запросы IN могут быть переписаны как (левые внешние) соединения и какой-то тип IS (NOT) NULL.например
SELECT * FROM FOO WHERE ID IN (SELECT ID FROM FOO2)
можно переписать как
SELECT FOO.* FROM FOO JOIN FOO2 ON FOO.ID=FOO2.ID
или
SELECT * FROM FOO WHERE ID NOT IN (SELECT ID FROM FOO2)
возможно
SELECT FOO.* FROM FOO
LEFT OUTER JOIN FOO2
ON FOO.ID=FOO2.ID WHERE FOO.ID IS NULL
создать представление для каждого подзапроса - это путь.Получил это работает как шарм.
Вы можете обойти эту проблему, создав отдельный VIEW для любого подзапроса, который вы хотите использовать, а затем присоединитесь к нему в создаваемом VIEW.Вот пример:http://blog.gruffdavies.com/2015/01/25/a-neat-mysql-hack-to-create-a-view-with-subquery-in-the-from-clause/
Это очень удобно, так как вы, скорее всего, все равно захотите использовать его повторно, и поможет вам сохранить SQL DRY.