2010-11-18 69 views
37

实施例:如何在表达式重用结果列另一个结果列

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

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

+0

取决于细节,如涉及的列和表。 – 2010-11-18 23:13:45

+0

@OMG Ponis:喜欢?没有这样的一般方法吗? – Wernight 2010-11-18 23:20:44

+0

我同意@OMG。也就是说,如果您可以编写* one *子查询作为列来返回“turnover”和“cost”,则围绕该子查询的查询可以执行“turnover-cost”。有关更多详细信息,我们需要一些关于您的架构的细节。 – 2010-11-18 23:21:28

回答

40

像这样:

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

通常,当您从'table1,table2'中选择时,您将获得两个表的CROSS JOIN。从(table1,table2)中选择bla'作为这两个表的作用是什么? – 2015-01-21 09:15:44

+1

@CharlBotha:它不是从(foo,bar)中选择的。它是[select](从foo中选择总和),(从栏中选择总和)[从无到有]。 – 2015-01-22 06:05:57

+0

在你上面的例子中,你有......(从......(选择......)作为营业额,(选择......)作为成本)作为partial_sums' - 我仍然想知道营业额和成本的精确度如何,选择结合? – 2015-01-22 07:09:17

4
SELECT turnover, cost, turnover - cost 
FROM 
(
SELECT 
(SELECT ...) as turnover, 
(SELECT ...) as cost 
) as Temp 
+0

这些是表别名,而不是列别名... – 2010-11-18 23:14:21

+0

如果营业额和成本是表别名,您绝对不能这样做:营业额 - 成本为利润 – 2010-11-18 23:17:53

+0

无效: 错误:FROM中的子查询必须有一个别名 提示:例如,FROM(SELECT ...)[AS] foo。 – Wernight 2010-11-18 23:22:44

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

在动物测试 - 你会先来! :-)

分享和享受。

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 

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

+0

你应该做的就是用'outertable'连接''bigcorrelatedsubquery'',而不是多次重复或使用concat hack。即使在最坏的情况下,你也可以将子查询作为CTE来避免重复。 – 2016-03-01 22:42:25

5

也许SQL“与”条款可以帮助,因为这里介绍http://orafaq.com/node/1879(其他数据库如Postgres里做得一样好,而不仅仅是甲骨文)。

+1

此功能称为“公用表表达式”又名CTE。请参阅http://stackoverflow.com/questions/2686919/is-possible-to-reuse-subqueries – Vadzim 2012-12-11 09:11:02

10

可以重用这样的查询:

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 

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

+0

这是让代码具有多个子查询可读性的最佳方法... – 2017-04-21 08:44:49

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 
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倍。

相关问题