如何在表达式中重用另一个结果列的结果列

时间:2010-11-18 23:09:11

标签: sql postgresql subquery

示例:

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

当然这是无效的(至少在Postgres中)但如何在不重写子查询两次的情况下在查询中实现相同的效果?

9 个答案:

答案 0 :(得分:42)

像这样:

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

答案 1 :(得分:12)

你可以重复使用这样的查询:

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

这里有一点需要注意。第一种方法更具可读性和可重用性,但第二种方法可能更快,因为数据库可能会为它选择更好的计划。

答案 2 :(得分:6)

也许sql“with”子句可以提供帮助,如此处所示http://orafaq.com/node/1879(其他数据库如Postgres也可以这样做,而不仅仅是oracle)。

答案 3 :(得分:4)

SELECT turnover, cost, turnover - cost
FROM
(
SELECT
(SELECT ...) as turnover,
(SELECT ...) as cost
) as Temp

答案 4 :(得分:4)

实际上我在这方面做了很多工作,打了很多砖墙,但终于找到了答案 - 更多的是黑客 - 但它工作得非常好,并将我的查询的读取开销减少了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

我现在拥有了我需要的所有三个相关的“标量”值,但只需执行一次相关的子查询而不是三次。

答案 5 :(得分:3)

我认为以下内容可行:

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);

未在动物身上进行测试 - 您将成为第一个! : - )

分享并享受。

答案 6 :(得分:0)

使用交叉申请或外部申请。

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

答案 7 :(得分:0)

这已经很老了,但我遇到了这个问题并看到了这篇文章,但没有设法用给定的答案来解决我的问题,所以我最终得出了这个解决方案:

如果您的查询是:

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秒 不确定它后来是否变成了DB的相同子查询的2倍。

答案 8 :(得分:-1)

您可以使用此类用户定义的变量

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