Выборка из общих табличных выражений (CTE)
Общие табличные выражения являются более сложной и более мощной вариацией производных таблиц.CTE состоят из преамбулы, начинающейся с ключевого слова WITH
. Преамбула определяет одно или более общих табличныхвыражений каждое из которых может иметь список алиасов полей. Основной запрос, который следует за преамбулой, может обращаться к CTE так, как будто обычные таблицы.CTE доступны любой части запроса ниже точки своего объявления.
Подробно CTE описываются в разделе Общие табличные выражения CTE (WITH … AS … SELECT),а здесь приведены лишь некоторые примеры использования.
Следующий запрос представляет наш пример с производной таблицей в варианте для общих табличных выражений:
WITH vars (b, D, denom) AS (
SELECT b, b*b - 4*a*c, 2*a
FROM coeffs
)
SELECT
IIF (D >= 0, (-b - sqrt(D)) / denom, NULL) AS sol_1,
IIF (D > 0, (-b + sqrt(D)) / denom, NULL) AS sol_2
FROM vars
Это не слишком большое улучшение по сравнению с вариантом с производными таблицами (за исключением того, что вычисления проводятся до основного запроса).Мы можем ещё улучшить запрос, исключив двойное вычисление sqrt(D) для каждой строки:
WITH vars (b, D, denom) AS (
SELECT b, b*b - 4*a*c, 2*a
FROM coeffs
),
vars2 (b, D, denom, sqrtD) AS (
SELECT
b, D, denom,
IIF (D >= 0, sqrt(D), NULL)
FROM vars
)
SELECT
IIF (D >= 0, (-b - sqrtD) / denom, NULL) AS sol_1,
IIF (D > 0, (-b + sqrtD) / denom, NULL) AS sol_2
FROM vars2
Текст запроса выглядит более сложным, но он стал более эффективным (предполагая, что исполнение функции SQRT
занимает больше времени, чем передача значений переменных b, d и denom через дополнительное CTE).
Note
|
На самом деле все столбцы, вычисляемые в CTE, будут перевычислены столько раз, сколько раз они указываются в основном запросе.Это важно может привести к неожиданным результатам при использовании недетерминированных функций.Следующий пример показывает сказанное:
результатом этого запроса будет C1 80AAECED-65CD-4C2F-90AB-5D548C3C7279 C2 C1214CD3-423C-406D-B5BD-95BF432ED3E3 C3 EB176C10-F754-4689-8B84-64B666381154 Для материализации результата функции
результатом этого запроса будет C1 80AAECED-65CD-4C2F-90AB-5D548C3C7279 C2 80AAECED-65CD-4C2F-90AB-5D548C3C7279 C3 80AAECED-65CD-4C2F-90AB-5D548C3C7279 или завернуть функцию GEN_UUID в подзапрос
Эта особенность текущей реализации и она может быть изменена в следующих версиях сервера. |
Конечно, мы могли бы добиться такого результата и с помощью производных таблиц, но это потребовало бы вложить запросы один в другой.