MySQL: просмотр с подзапросом в ограничении FROM FROM

В 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

Ответ 1

Ваш запрос не может быть записан так:

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

Ответ 2

У меня была та же проблема. Я хотел создать представление, чтобы показать информацию за последний год, из таблицы с записями с 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 без значительного штрафа за скорость (по сравнению с выполнением исходный подзапрос выбирается без каких-либо просмотров).

Ответ 3

Это, как известно, известная проблема.

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

Ответ 4

создать представление для каждого подзапроса - это путь. Это работает как шарм.

Ответ 5

Вы можете обойти это, создав отдельный VIEW для любого подзапроса, который вы хотите использовать, а затем присоединитесь к тому, что вы создаете. Вот пример: http://blog.gruffdavies.com/2015/01/25/a-neat-mysql-hack-to-create-a-view-with-subquery-in-the-from-clause/

Это очень удобно, так как вы, скорее всего, захотите снова его использовать и сможете сохранить свой SQL DRY.