Выборка из производной таблицы (derived table)
Производная таблица — это корректная команда SELECT
, заключённая в круглые скобки, опционально обозначенная псевдонимом таблицы и псевдонимами полей.
<derived table> ::= (<select-query>) [[AS] derived-table-alias] [(<derived-column-aliases>)] <derived-column-aliases> := column-alias [, column-alias ...] <lateral-derived-table> ::= LATERAL <derived-table>
Возвращаемый набор данных такого оператора представляет собой виртуальную таблицу, к которой можно составлять запросы, так как будто это обычная таблица.
Производная таблица в запросе ниже выводит список имён таблиц в базе данных и количество столбцов в них.Запрос к производной таблице выводит количество полей, и количество таблиц с таким количеством полей.
SELECT
FIELDCOUNT,
COUNT(RELATION) AS NUM_TABLES
FROM (SELECT
R.RDB$RELATION_NAME RELATION,
COUNT(*) AS FIELDCOUNT
FROM RDB$RELATIONS R
JOIN RDB$RELATION_FIELDS RF
ON RF.RDB$RELATION_NAME = R.RDB$RELATION_NAME
GROUP BY RELATION)
GROUP BY FIELDCOUNT
Тривиальный пример, демонстрирующий использование псевдонима производной таблицы и списка псевдонимов столбцов (оба опциональные):
SELECT
DBINFO.DESCR, DBINFO.DEF_CHARSET
FROM (SELECT *
FROM RDB$DATABASE) DBINFO (DESCR, REL_ID, SEC_CLASS, DEF_CHARSET)
Note
|
Примечания:
|
Приведём пример того, как использование производных таблиц может упростить решение некоторой задачи.
Предположим, что у нас есть таблица COEFFS
, содержащая коэффициенты для ряда квадратных уравнений, которые мы собираемся решить.Она может быть определена примерно так:
CREATE TABLE coeffs (
a DOUBLE PRECISION NOT NULL,
b DOUBLE PRECISION NOT NULL,
c DOUBLE PRECISION NOT NULL,
CONSTRAINT chk_a_not_zero CHECK (a <> 0)
)
В зависимости от значений коэффициентов a, b и c, каждое уравнение может иметь ноль, одно или два решения.Мы можем найти эти решения с помощью одноуровневого запроса к таблице 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
(SELECT b, b*b - 4*a*c, 2*a FROM coeffs) (b, D, denom)
Если мы захотим показывать коэффициенты рядом с решениями уравнений, то мы можем модифицировать запрос следующим образом:
SELECT
a, b, c,
IIF (D >= 0, (-b - sqrt(D)) / denom, NULL) sol_1,
IIF (D > 0, (-b + sqrt(D)) / denom, NULL) sol_2
FROM
(SELECT a, b, c, b*b - 4*a*c AS D, 2*a AS denom
FROM coeffs)
Обратите внимание, что в первом запросе мы назначили алиасы для всех полей производной таблицы в виде списка после таблицы, а во втором, по мере необходимости, добавляем алиасы внутри запроса производной таблицы.Оба этих метода корректны, так как при правильном применении гарантируют, что каждое поле производной таблицы имеет уникальное имя.
Note
|
На самом деле все столбцы, вычисляемые в производной таблице, будут перевычислены столько раз, сколько раз они указываются в основном запросе.Это важно может привести к неожиданным результатам при использовании недетерминированных функций.Следующий пример показывает сказанное:
результатом этого запроса будет C1 80AAECED-65CD-4C2F-90AB-5D548C3C7279 C2 C1214CD3-423C-406D-B5BD-95BF432ED3E3 C3 EB176C10-F754-4689-8B84-64B666381154 Для материализации результата функции GEN_UUID вы можете воспользоваться следующим способом:
результатом этого запроса будет C1 80AAECED-65CD-4C2F-90AB-5D548C3C7279 C2 80AAECED-65CD-4C2F-90AB-5D548C3C7279 C3 80AAECED-65CD-4C2F-90AB-5D548C3C7279 или завернуть функцию GEN_UUID в подзапрос
Эта особенность текущей реализации и она может быть изменена в следующих версиях сервера. |