Предложение 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. Оба они не работают.

Ответы:


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.




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;
Клаус
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.