Как повторно использовать столбец результатов в выражении для другого столбца результатов - PullRequest
46 голосов
/ 19 ноября 2010

Пример:

SELECT
   (SELECT SUM(...) FROM ...) as turnover,
   (SELECT SUM(...) FROM ...) as cost,
   turnover - cost as profit

Конечно, это неверно (по крайней мере, в Postgres), но как добиться того же в запросе, не переписывая подзапрос дважды?

Ответы [ 9 ]

42 голосов
/ 21 июля 2011

Вроде так:

SELECT
   turnover,
   cost,
   turnover - cost as profit
from (
   (SELECT SUM(...) FROM ...) as turnover,
   (SELECT SUM(...) FROM ...) as cost
   ) as partial_sums
12 голосов
/ 21 февраля 2014

Вы можете повторно использовать запрос следующим образом:

WITH 
  TURNOVER AS (
    SELECT SUM(...) FROM ...)
  ),
  COST AS(
    SELECT SUM(...) FROM ...
  )

SELECT *
FROM(
 SELECT
   TURNOVER.sum as SUM_TURNOVER
 FROM
 TURNOVER,COST
 WHERE ....
) AS a

Это эквивалентно:

SELECT *
FROM(
 SELECT
   TURNOVER.sum as SUM_TURNOVER
 FROM
 (
   SELECT SUM(...) FROM ...)
 )AS TURNOVER,
 (
   SELECT SUM(...) FROM ...
 )AS COST
 WHERE ....
) AS a

Здесь есть примечание.Первый метод более читабелен и пригоден для повторного использования, но второй метод может быть быстрее, потому что БД может выбрать лучший план для него.

6 голосов
/ 19 октября 2011

Возможно, может помочь предложение sql "with", как представлено здесь http://orafaq.com/node/1879 (другие базы данных, такие как Postgres, тоже это делают, а не просто оракул).

4 голосов
/ 21 июля 2011

На самом деле я проделал большую работу над этим и ударил по многим кирпичным стенам, но, в конце концов, нашел ответ - скорее хак - но это сработало очень хорошо и снизило накладные расходы на чтение моих запросов на 90% ... .

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

Так что вместо

select a,b,
(select x from bigcorrelatedsubquery) as x,
(select y from bigcorrelatedsubquery) as y,
(select z from bigcorrelatedsubquery) as z
from outertable

Я сейчас делаю

select a,b,
(select convert(varchar,x)+','+convert(varchar,x)+','+convert(varchar,x)+',' 
from bigcorrelatedsubquery) from bigcorrelatedquery) as xyz
from outertable
group by country

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

4 голосов
/ 19 ноября 2010
SELECT turnover, cost, turnover - cost
FROM
(
SELECT
(SELECT ...) as turnover,
(SELECT ...) as cost
) as Temp
3 голосов
/ 19 ноября 2010

Я думаю, что будет работать следующее:

SELECT turnover, cost, turnover-cost as profit FROM
   (SELECT 1 AS FAKE_KEY, SUM(a_field) AS TURNOVER FROM some_table) a
INNER JOIN
   (SELECT 1 AS FAKE_KEY, SUM(a_nother_field) AS COST FROM some_other_table) b
USING (FAKE_KEY);

Не тестировано на животных - вы будете первыми!: -)

Делись и наслаждайся.

0 голосов
/ 31 марта 2017

это довольно старый, но я столкнулся с этой проблемой и увидел этот пост, но мне не удалось решить мою проблему, используя приведенные ответы, поэтому я в итоге пришел к такому решению:

если ваш запрос:

SELECT
   (SELECT SUM(...) FROM ...) as turnover,
   (SELECT SUM(...) FROM ...) as cost,
   turnover - cost as profit

вы можете превратить его в подзапрос, а затем использовать такие поля, как:

SELECT *,(myFields.turnover-myFields.cost) as profit 
FROM
(      
SELECT
       (SELECT SUM(...) FROM ...) as turnover,
       (SELECT SUM(...) FROM ...) as cost

) as myFields

Я не совсем уверен, что это плохой способ работы, но с точки зрения производительности это кажетсяхорошо, для меня запрос на 224,000 записей занял 1,5 секунды, но я не уверен, превратился ли он позже в 2х того же подзапроса по БД.

0 голосов
/ 23 января 2017

Используйте перекрестное или внешнее применение.

SELECT
  Calc1.turnover,
  Calc2.cost,
  Calc3.profit
from
   cross apply ((SELECT SUM(...) as turnover FROM ...)) as Calc1
   cross apply ((SELECT SUM(...) as cost FROM ...)) as Calc2

   /*
     Note there is no from Clause in Calc 3 below.
     This is how you can "stack" formulas like in excel.
     You can return any number of columns, not just one.
   */
   cross apply (select Calc1.turnover - Calc2.cost as profit) as Calc3
0 голосов
/ 20 июля 2016

Вы можете использовать пользовательские переменные, подобные этой

SELECT
   @turnover := (SELECT SUM(...) FROM ...),
   @cost := (SELECT SUM(...) FROM ...),
   @turnover - @cost as profit

http://dev.mysql.com/doc/refman/5.7/en/user-variables.html

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