MySQL еквівалент WITH в Oracle


Відповіді:


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. У більш складних запитах код потрібно було б писати кілька разів.


Щоб уникнути повторення (дублювання коду), чи не було б краще використовувати змінні та тимчасові таблиці?
Pacerier

Я б не хвилювався з приводу дублювання коду, але, безумовно, розглядаю і спробую версію з тимчасовими таблицями з міркувань продуктивності.
ypercubeᵀᴹ

1
Чому ти кажеш, що ти б не переймався дублюванням коду? Це прямо безладно і НЕ  СУХО .
Pacerier

1
@Pacerier DRY не завжди стосується коду DB.
JNK

1
@Pacerier Я не був би здивований, якби не він. Двигуни БД повинні чітко здогадуватися про те, що буде найкраще працювати, але все ж гарантуючи повернення правильних результатів. Таблиці темпів взагалі чудово, але DRY призводить до жахливої ​​продуктивності в БД в інших аспектах, як-от визначені користувачем функції.
JNK

2

Це спрацює, але шкода, що він не надасть переваги використання пункту WITH, тобто не виконувати один і той же запит кілька разів (складні запити можуть бути реально повільними і дуже вимогливими до двигуна бази даних; я зазнав цього) .

Я б запропонував вставити кожен пункт SELECT, визначений у вихідному пункті, до своєї тимчасової таблиці та використовувати їх всередині запиту . У MySQL тимчасова таблиця опуститься після закінчення сеансу роботи користувача.

Редагувати:

Я щойно побачив цю відповідь у подібній темі, яка чітко розкриває 3 обхідні варіанти MySQL :

  • ЧАСОВІ таблиці
  • ВИЗНАЧЕННІ таблиці
  • вбудовані погляди (фактично те, що являє собою пункт WH - вони взаємозамінні)

/programming//a/1382618/2906290

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.