Реліз MySQL 8

  • [рекурсивні] ОТВ,(англійською Узагальнені Табличні Вирази це Common Table Expressions, тому в англомовній літературі використовується абревіатура CTE)
  • [рекурсивні] factoring підзапити,
  • оператор WITH [RECURSIVE].

3 роки тому я показав як можна емулювати ОТВ, але зараз в MySQL реалізовані справжні ОТВ, не ерзац!

Похідні таблиці це підзапит у частині FROM, виділений жирним нижче:

SELECT … FROM(SELECT …) AS derived_table;

Похідні таблиці існують у MySQL давно. Можна сміливо сказати, що нерекурсивні ОТВ є " поліпшеної версією похідних таблиць " . Ось перший приклад:

WITH cte1 (txt) AS (SELECT "This"), cte2 (txt) AS (SELECT CONCAT (cte1.txt, "is a") FROM cte1), cte3 (txt) AS (SELECT "nice query" UNION SELECT "query that rocks" UNION SELECT "query" ) , cte4 ( txt ) AS ( SELECT concat ( cte2.txt, cte3.txt ) FROM cte2, cte3 ) SELECT MAX (txt), MIN (txt) FROM cte4;

Однак, якщо ви порівняєте ці запити, то помітите, що перший простіше для сприйняття, оскільки таблиці визначаються послідовно одна за одною, і ми, читаючи зверху донизу, бачимо, як формуються речення; другий же має деревоподібну структуру вивернуту навиворіт (найперше слово "This" вкладено найглибше). ОТВ скорочують код і роблять його інтуїтивно зрозумілим, що полегшує його подальший супровід.

Через обмеження на розмір статті, я докладно розгляну нерекурсивні ВТВ у наступному матеріалі – сподіваюся, що приклад вище розігрів ваш інтерес до них. Зараз я зосереджуся на рекурсивних ОТВ, які, на мою скромну думку, надають набагато більшенових можливостей порівняно з нерекурсивними ВТВ.

Рекурсивні ОТВ - це набір рядків, які виходять шляхом послідовних ітерацій: на основі початкового набору рядків обчислюються нові рядки, які додаються до початкового набору, і нові рядки знову залучаються до процесу обчислення наступних рядків доти, доки на черговому етапі не буде зроблено нульове кількість рядків. (Зверніть увагу, у процесі обчислення нових рядків беруть участь лише рядки, отримані на попередньому етапі, а не весь об'єднаний набір.)

Максимально простий синтаксис для рекурсивних ОТВ має вигляд:

WITH RECURSIVE cte_name AS ( SELECT. (SELECT AVG(n) FROM my_cte);

SELECT * FROM numbers; + ------+ n + ------+ 0 2 3 0 0 2 3 0 + ------+ 8 rows in set ( 0 , 00 sec )

Схожий приклад, де ОТВ цілком визначено всередині підзапиту, а не перед ключовим словом DELETE: