SQL 如何将表达式中的结果列重用于另一个结果列

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4220587/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-01 08:20:45  来源:igfitidea点击:

How to reuse a result column in an expression for another result column

sqlpostgresqlsubquery

提问by Wernight

Example:

例子:

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

Sure this is invalid (at least in Postgres) but how to achieve the same in a query without rewriting the sub-query twice?

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

采纳答案by Denis de Bernardy

Like so:

像这样:

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

回答by Alex Calugarescu

You could reuse the query like this:

您可以像这样重用查询:

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

This is equivalent to :

这相当于:

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

There is a point to note here. The first method is more readable and reusable, but the second method might be faster, because the DB might choose a better plan for it.

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

回答by andrers52

Perhaps the sql "with" clause could help, as presented here http://orafaq.com/node/1879(other databases such as Postgres do it as well, not just oracle).

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

回答by Eric.K.Yung

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

回答by bhealy

Actually I did a lot of work on this, and hit many brick walls, but finally figured out an answer - more of a hack - but it worked very well and reduced the read overhead of my queries by 90%....

实际上我在这方面做了很多工作,并撞到了很多砖墙,但最终找到了一个答案——更像是一个黑客——但它工作得很好,并将我的查询的读取开销减少了 90%....

So rather than duplicating the correlated query many times to retrieve multiple columns from the subquery, I just used concat all the values I want to return into a comma separated varchar, and then unroll them again in the application...

因此,我没有多次复制相关查询以从子查询中检索多个列,而是将所有要返回的值连接到逗号分隔的 varchar 中,然后在应用程序中再次展开它们...

So instead of

所以代替

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

I now do

我现在做

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

I now have all three correlated 'scalar' values I needed but only had to execute the correlated subquery once instead of three times.

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

回答by Bob Jarvis - Reinstate Monica

I think the following will work:

我认为以下将起作用:

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

Not tested on animals - you'll be first! :-)

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

Share and enjoy.

分享和享受。

回答by William Egge

Use a cross apply or outer apply.

使用交叉应用或外部应用。

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

回答by Niklas

this is pretty old but i ran into this problem and saw this post but didnt manage to solve my problem using the given answers so i eventually arrived at this solution :

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

if your query is :

如果您的查询是:

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

you can turn it into a subquery and then use the fields such as :

您可以将其转换为子查询,然后使用以下字段:

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

) as myFields

i'm not entirely sure if this is a bad way of doing things but performance wise it seems okay for me querying over 224,000records took 1.5 sec not sure if its later on turned into 2x of the same sub query by DB.

我不完全确定这是否是一种糟糕的做事方式,但从性能上看,我查询224,000记录需要 1.5 秒,不确定它后来是否变成了 DB 相同子查询的 2 倍。

回答by Dinesh

You can use user defined variables like this

您可以像这样使用用户定义的变量

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

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