Застереження 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

Інші продукти RDBMS, які підтримують загальні вирази таблиць:


1
SQLite підтримує пропозицію WITH, починаючи з версії 3.8.3, випущеної 03.02.2014.
Martijn

Я додав до списку H2 та Firebird.
a_horse_with_no_name

2
@BillKarwin: Я не вірю, що MySQL ніколи не реалізує жодної сучасної функції СУБД (перевірити обмеження, функцію вікна, індекс виразів, частковий індекс, відкладені обмеження ...).
a_horse_with_no_name

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) UNION ALL (вибрати * з таблиці2)) Згрупувати за чимось?

1
@Kathy Привіт, Subqueryце ім'я, яке я використав для самої похідної таблиці. Коли ви використовуєте, from ( ... )ви створюєте щось на зразок тимчасової таблиці (похідної таблиці), і для неї потрібно ім'я. Тому я використовував as Subquery. Відповідаючи на ваше запитання, так, ви можете, але вам доведеться додати ім'я до зовнішньої похідної таблиці (безпосередньо перед Group By). Сподіваюся, що допомогло.
Мості Мостачо

@MostyMostacho Здрастуйте, не могли б ви нагодувати мене ложкою тут трохи? Я намагаюся перетворити його на MySQL. Чи можете ви поглянути на це? посилання або відповідь на моє запитання тут, можливо? посилання
Пранав

13

Ви правильно встановили синтаксис:

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

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

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

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


9

Oracle підтримує WITH.

Це виглядало б так.

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
А, бачу. Це пункт виділення, який передує виділенню. Чи можна його використовувати також у CREATE VIEW? Чим він відрізняється від приєднання до підвибору? Я не бачу в Інтернеті прикладів, коли в назві після СО є параметри - як це працює?
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

Можливо, вам захочеться скористатися текстовим редактором із можливостями макросу для перетворення списку значень у цитоване пропозицію вибору об'єднання.




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.