Предложение MySQL «WITH»

98

Я пытаюсь использовать MySQL для создания представления с предложением "WITH"

WITH authorRating(aname, rating) AS
   SELECT aname, AVG(quantity)
   FROM book
   GROUP BY aname

Но похоже, что MySQL не поддерживает это.

Я думал, что это довольно стандартно, и я уверен, что Oracle поддерживает это. Есть ли способ заставить MySQL использовать предложение «WITH»? Я пробовал это с движком MyISAM и innoDB. Оба они не работают.

shA.t
источник

Ответы:

109

Обновление: MySQL 8.0 наконец-то получил функцию общих табличных выражений, включая рекурсивные CTE.

Вот блог, объявляющий об этом: http://mysqlserverteam.com/mysql-8-0-labs-recursive-common-table-expressions-in-mysql-ctes/

Ниже мой предыдущий ответ, который я написал в 2008 году.


MySQL 5.x не поддерживает запросы, использующие WITHсинтаксис, определенный в SQL-99, также называемый общими табличными выражениями.

Это запрос функции для MySQL с января 2006 года: http://bugs.mysql.com/bug.php?id=16244

Другие продукты СУБД, поддерживающие общие табличные выражения:

Билл Карвин
источник
1
SQLite поддерживает предложение WITH с версии 3.8.3, выпущенной 03.02.2014.
Martijn
Я добавил в список H2 и Firebird.
a_horse_with_no_name 04
2
@BillKarwin: Я не верю, что MySQL когда-либо будет реализовывать какие-либо современные возможности СУБД (проверочные ограничения, оконная функция, индекс по выражениям, частичный индекс, отложенные ограничения ...).
a_horse_with_no_name 04
2
@a_horse_with_no_name, они, кажется, придают гораздо более высокий приоритет масштабируемости. Они долгое время сосредоточились на том, чтобы сделать свои внутренние устройства более масштабируемыми, чтобы использовать преимущества современного оборудования. Но я думаю, что они пренебрегли возможностями SQL.
Билл Карвин
1
@BlakeMcBride, Вы ошибаетесь, ваш комментарий FUD и фактически не имеет под собой никаких оснований. Oracle также владеет другими продуктами для баз данных, которые делают то, что не удается Oracle DB. Примеры: TimesTen, BerkeleyDB. Они приобрели эти базы данных, чтобы расширить свой рынок. MySQL доминирует на рынке веб-приложений, а Oracle DB - нет, поэтому они приобрели MySQL. Oracle не имеет смысла ограничивать MySQL. Я разговаривал с разработчиками Oracle MySQL на конференции в апреле, и они фактически работают над внедрением WITH для MySQL.
Билл Карвин
17

Возможно, вам будет интересно что-нибудь вроде этого:

select * from (
    select * from table
) as Subquery
Мосты Мостачо
источник
не могли бы вы объяснить подзапрос? Могу ли я выбрать * из ((выбрать * из таблицы1) ОБЪЕДИНЕНИЕ ВСЕХ (выбрать * из таблицы2)) Группировать по чему-то?
1
@Kathy Привет, Subqueryэто имя, которое я использовал для самой производной таблицы. Когда вы используете, from ( ... )вы создаете что-то вроде временной таблицы (производной таблицы), и для нее требуется имя. Вот почему я использовал as Subquery. Отвечая на ваш вопрос, да, вы можете, но вам нужно будет указать имя внешней производной таблицы (непосредственно перед Group By). Надеюсь, это помогло.
Мосты Мостачо
@MostyMostacho Привет, пожалуйста, покорми меня немного с ложечки? Я изо всех сил пытаюсь преобразовать его в MySQL. Вы можете взглянуть на это? ссылка или ответ на мой вопрос здесь может быть? link
Pranav
13

Синтаксис у вас правильный:

WITH AuthorRating(AuthorName, AuthorRating) AS
   SELECT aname         AS AuthorName,
          AVG(quantity) AS AuthorRating
   FROM Book
   GROUP By Book.aname

Однако, как уже упоминалось, MySQL не поддерживает эту команду. WITH был добавлен в SQL: 1999; новейшая версия стандарта SQL - SQL: 2008. Вы можете найти дополнительную информацию о базах данных, поддерживающих различные функции SQL: 1999, в Википедии .

MySQL традиционно немного отставал в поддержке стандарта SQL, в то время как коммерческие базы данных, такие как Oracle, SQL Server (недавно) и DB2, следовали им чуть более внимательно. PostgreSQL, как правило, также хорошо соответствует стандартам.

Возможно, вы захотите взглянуть на дорожную карту MySQL; Я не совсем уверен, когда эта функция может поддерживаться, но она отлично подходит для создания читаемых сводных запросов.

Эд Альторфер
источник
10

Oracle поддерживает СО.

Это выглядело бы так.

WITH emps as (SELECT * FROM Employees)
SELECT * FROM emps WHERE ID < 20
UNION ALL
SELECT * FROM emps where Sex = 'F'

@ysth WITH сложно использовать в Google, потому что это обычное слово, которое обычно исключается из поиска.

Вы бы хотели посмотреть документацию SELECT, чтобы увидеть, как работает факторинг подзапросов.

Я знаю, что это не отвечает на OP, но я убираю любую путаницу, которая могла начаться.


источник
Во всяком случае, мое замешательство не прояснилось. Вы хотите сказать, что предложения WITH нет, но есть инструкция WITH?
ysth
1
Ах я вижу. Это предложение select, которое предшествует select. Можно ли его использовать и в CREATE VIEW? Чем это отличается от присоединения к подзапросу? Я не вижу в Интернете примеров, где имя после WITH имеет параметры - как они работают?
ysth
1
Это совсем другое. Обратите внимание, что одна и та же подзапрос используется дважды без необходимости определять ее дважды. Конечно, вы можете скопировать / вставить туда тот же запрос, но это простой пример. Представьте, что предложение WITH продолжалось для страницы и использовалось 4 раза в основном запросе. тогда вы это оцените.
Я связался с документами, которые должны объяснить синтаксис. Насколько в поле зрения. Конечно, там это работает.
3

Основываясь на ответе @Mosty Mostacho, вот как вы могли бы сделать что-то эквивалентное в MySQL для конкретного случая определения того, какие записи не существуют в таблице и не находятся в какой-либо другой базе данных.

select col1 from (
   select 'value1' as col1 union
   select 'value2' as col1 union
   select 'value3' as col1
) as subquery
left join mytable as mytable.mycol = col1
where mytable.mycol is null
order by col1

Вы можете использовать текстовый редактор с возможностями макросов для преобразования списка значений в указанное в кавычках предложение select union.

Рувим
источник
1
   WITH authorRating as (select aname, rating from book)
   SELECT aname, AVG(quantity)
   FROM authorRating
   GROUP BY aname
Мантас Дайнис
источник
0

Вы когда-нибудь пробовали временную таблицу? Это решило мою беседу:

create temporary table abc (
column1 varchar(255)
column2 decimal
);
insert into abc
select ...
or otherwise
insert into abc
values ('text', 5.5), ('text2', 0815.8);

Затем вы можете использовать эту таблицу при каждом выборе в этом сеансе:

select * from abc inner join users on ...;
Клаус
источник
1
Я должен отметить: stackoverflow.com/questions/343402/… вы не можете открыть таблицу дважды :-(
Клаус
Мое решение для небольших наборов данных в таблицах: создайте таблицу abc2 как abc; вставить в abc2 выбрать * из abc;
Клаус