Есть ли MySQL эквивалент предложения WITH в Oracle?
Есть ли MySQL эквивалент предложения WITH в Oracle?
Ответы:
Нет. Если (пока) кто-то не разработает его (MySQL с открытым исходным кодом, любой может внести свой вклад).
WITH
Ключевое слово ANSI / ISO SQL используется для определения общих табличных выражений (CTE) и упрощает сложные запросы с одной или несколькими вложенными ссылками. Он доступен в Oracle, Postgres, SQL-Server, DB2, но не в MySQL.
Последний запрос может иметь ссылки (обычно в FROM
предложении, но они могут быть в любой другой части) на любое из общих табличных выражений, один или несколько раз. Запрос может быть написан (без CTE) в MySQL, используя производные таблицы, но ссылки должны быть сделаны повторно.
Пример глупого запроса, показывающего всех людей, родившихся в 50-х и в июле месяце, и число всех людей, родившихся в том же году:
WITH a AS
( SELECT name, birthdate, YEAR(birthdate) AS birthyear
FROM persons
WHERE birthdate >= '1950-01-01' AND birthdate < '1960-01-01'
)
, b AS
( SELECT birthyear, COUNT(*) AS cnt
FROM a
GROUP BY birthyear
)
SELECT a.name, a.birthdate, b.cnt AS number_of_births
FROM a JOIN b
ON a.birthyear = b.birthyear
WHERE MONTH(a.birthdate) = 7 ;
В MySQL это можно записать так:
SELECT a.name, a.birthdate, b.cnt AS number_of_births
FROM
( SELECT name, birthdate, YEAR(birthdate) AS birthyear
FROM persons
WHERE birthdate >= '1950-01-01' AND birthdate < '1960-01-01'
) AS a
JOIN
( SELECT birthyear, COUNT(*) AS cnt
FROM
( SELECT name, birthdate, YEAR(birthdate) AS birthyear
FROM persons
WHERE birthdate >= '1950-01-01' AND birthdate < '1960-01-01'
) AS aa
GROUP BY birthyear
) AS b
ON a.birthyear = b.birthyear
WHERE MONTH(a.birthdate) = 7 ;
Обратите внимание на дублирование кода для производной таблицы a
. В более сложных запросах код должен быть написан несколько раз.
Это будет работать, но жаль, что оно не даст преимущества использования предложения WITH, то есть не для выполнения одного и того же запроса несколько раз (сложные запросы могут быть слишком медленными и очень сложными для механизма базы данных; я пострадал) ,
Я бы предложил вставить каждый SELECT, определенный в оригинальном предложении WITH, в его собственную временную таблицу и использовать их внутри запроса . В MySQL временная таблица будет удалена после завершения сеанса пользователя.
РЕДАКТИРОВАТЬ:
Я только что видел этот ответ в похожей теме, в которой четко представлены 3 обходных пути с MySQL :
/programming//a/1382618/2906290
и пример процедуры MySQL, которая создает и удаляет временные таблицы на случай, если вы продолжите сеанс и захотите освободить эти ресурсы (я бы использовал это просто в качестве примера синтаксиса): /programming//a/ 5553145/2906290