Рассмотрим упрощенный пример:
SELECT
lengthy_expression AS a,
g(a) AS b,
h(a) AS c,
...
FROM
my_table
Здесь lengthy_expression
представляет сложное выражение, которое использует несколько полей из my_table
и занимает несколько строк. Его результат используется для вычисления двух других полей b
и c
. Тем не менее, вышеупомянутое не допускается в стандартном SQL, потому что выражение в предложении WHERE
не может ссылаться на результат другого выражения в предложении WHERE
(почему бы не выйти за рамки меня).
Наивный вариант - повторить lengthy_expression
, но этого я явно хочу избежать.
Один вариант - использовать подзапрос:
SELECT
a,
g(a) AS b,
h(a) AS c,
...
FROM (
SELECT
lengthy_expression AS a,
...
FROM
my_table
)
Но, как вы можете видите, теперь мне нужно повторить другие поля ...
, которые нужны внешнему запросу.
Может быть, тогда подзапрос с объединением?
SELECT
a,
g(a) AS b,
h(a) AS c,
...
FROM
my_table
INNER JOIN (
SELECT
lengthy_expression AS a
FROM
my_table
) USING id
Это работает, но теперь есть ( возможно, дорогое) объединение, которое не преследует никакой цели, кроме как для обеспечения удобства чтения запроса. И это даже не очень хорошо подходит для этой цели, потому что lengthy_expression
спрятан ниже точки, где он используется, и читатель должен прыгнуть повсюду, чтобы узнать, что происходит.
Альтернативой является использование CTE:
WITH
my_table_with_a AS (
SELECT
*,
lengthy_expression AS a
FROM
my_table
)
SELECT
*,
g(a) AS b,
h(a) AS c,
...
FROM
my_table_with_a
По крайней мере, теперь порядок чтения более или менее соответствует логическому порядку, в котором происходят операции, но он довольно многословен, и найти хорошее имя для my_table_with_a
сложно. Тем более, что на практике я повторяю этот шаблон два или три раза.
Есть ли лучший способ сделать это?