PostgreSQL - использовать ранее вычисленное значение из того же запроса - PullRequest
2 голосов
/ 21 февраля 2011

У меня есть следующий запрос sql:

SELECT (SELECT ...) AS X, (SELECT ...) AS Y from my_table

'X' довольно сложно вычислить, и он используется как вход для вычисления Y. Однако, если я пытаюсь ссылаться на X в запросе, который вычисляет Y или даже в основном запросе, я получаю следующее сообщение об ошибке:

Error: column "X" does not exist

Есть ли способ ссылаться на X после его вычисления? Я действительно не хочу вычислять это дважды, поскольку это кажется очень неэффективным.

Ответы [ 3 ]

3 голосов
/ 22 февраля 2011

PostgreSQL, как правило, довольно умен, так как не нужно вычислять одно и то же дважды. Так что запрос вроде

SELECT (SELECT hard_to_compute FROM whatever) AS X,
       (SELECT hard_to_compute FROM whatever)*2 AS Y 
FROM my_table

необходимо выполнить два подзапроса только один раз. Однако, если запрос похож на

SELECT (SELECT hard_to_compute FROM whatever) AS X,
       (SELECT hard_to_compute*2 FROM whatever) AS Y 
FROM my_table

тогда оптимизатору будет сложнее увидеть, что является одинаковым в двух запросах.

Другой способ справиться с этим - создать функцию STABLE для вычисления X. Пока входные данные одинаковы, функции STABLE всегда возвращают один и тот же результат в пределах одного оператора, поэтому Postgres знает, что его нужно запустить только один раз. , Смотри http://www.postgresql.org/docs/9.0/interactive/xfunc-volatility.html.

2 голосов
/ 21 февраля 2011

Подвыбор может сделать это для вас, например ::100100

select *, hard_to_compute * 2 as using_hard_to_compute \
from (select *, (i * i) as hard_to_compute from foo) bar;

 i | hard_to_compute | using_hard_to_compute 
---+-----------------+-----------------------
 1 |               1 |                     2
 2 |               4 |                     8
 3 |               9 |                    18

Конечно, i * i на самом деле не сложно вычислить. Я просто притворяюсь, что это для этого примера.

0 голосов
/ 21 февраля 2011

Лучше всего сначала выполнить часть запроса (SELECT ...) AS X, сохранив его результаты во временной таблице.Затем используйте эту временную таблицу в вашем основном запросе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...