MySQL эквивалент СО в оракуле

Ответы:

16

Нет. Если (пока) кто-то не разработает его (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. В более сложных запросах код должен быть написан несколько раз.

ypercubeᵀᴹ
источник
Чтобы избежать повторения (дублирования кода), не лучше ли использовать переменные и временные таблицы?
Pacerier
Я бы не беспокоился о дублировании кода, но, конечно, я бы рассмотрел и попробовал версию с временными таблицами, из соображений производительности.
ypercubeᵀᴹ
1
Почему вы говорите, что не будете беспокоиться о дублировании кода? Это просто грязно и  сухо .
Pacerier
1
@Pacerier DRY не всегда имеет отношение к коду БД.
JNK
1
@Pacerier Я бы не удивился, если бы не было. Механизмам БД необходимо делать обоснованные предположения о том, что будет работать лучше, и в то же время гарантировать правильные результаты. В общем, временные таблицы хороши, но DRY приводит к ужасной производительности в БД в других отношениях, таких как пользовательские функции.
JNK
2

Это будет работать, но жаль, что оно не даст преимущества использования предложения WITH, то есть не для выполнения одного и того же запроса несколько раз (сложные запросы могут быть слишком медленными и очень сложными для механизма базы данных; я пострадал) ,

Я бы предложил вставить каждый SELECT, определенный в оригинальном предложении WITH, в его собственную временную таблицу и использовать их внутри запроса . В MySQL временная таблица будет удалена после завершения сеанса пользователя.

РЕДАКТИРОВАТЬ:

Я только что видел этот ответ в похожей теме, в которой четко представлены 3 обходных пути с MySQL :

  • ВРЕМЕННЫЕ столы
  • Производные таблицы
  • встроенные представления (фактически, что представляет собой предложение WITH - они взаимозаменяемы)

/programming//a/1382618/2906290

и пример процедуры MySQL, которая создает и удаляет временные таблицы на случай, если вы продолжите сеанс и захотите освободить эти ресурсы (я бы использовал это просто в качестве примера синтаксиса): /programming//a/ 5553145/2906290

Рауль Морено
источник