如何使用计算列在同一视图中计算另一列

102
我希望您能帮助我解答这个问题。我正在使用Oracle SQL(SQL Developer来查看)...
如果我有一个表,其中包含以下列:
ColumnA(数字)
ColumnB(数字)
ColumnC(数字)
在我的视图中,我有:
Select  
ColumnA,
ColumnB,
ColumnA + ColumnB As calccolumn1

现在我想使用calccolumn1,但我不能只是说...

Select  
ColumnA,
ColumnB,
ColumnA + ColumnB As calccolumn1
calccolumn1 / ColumnC as calccolumn2

我假设我需要某种子查询,但这就是我需要你的帮助的地方...我应该如何编写查询语句,以便我可以在同一查询中使用calccolumn1进行另一个计算?可能是If then或Case when,但归根结底它是一些派生数字。


1
有什么理由不直接执行 (ColumnA + ColumnB) / ColumnC As calccolumn2 吗? - Alex Poole
7
在这个简化的例子中,我同意......那应该是可行的。我想要表达的概念是如何将一个简化的例子格式化以适用于更复杂的情况......所以如果ColumnA是一个复杂的Case When语句,而ColumnB也是......那么如果我想要将它们组合起来生成calccolumn1,然后稍后用于生成calccolumn2,我是否只需将整个Column A 的Case语句放入()中,并对B执行相同的操作,然后将它们加在一起? - Ewaver
1
@AlexPoole 在同一级别上具有复杂表达式可能很方便。单个定义比在多个地方复制它更易于维护。可以使用CROSS APPLY方法来实现。 - Lukasz Szozda
当然,这个问题并没有真正显示出复杂的表达方式。我本来想说,在问这个问题时cross apply是不可用的,但是12c当时已经发布了几个月了,只是我不知道而已... 不过子查询的方法也不需要重复它。 - Alex Poole
@AlexPoole,使用内联视图/CTE方法没有任何问题。我只是想表明,在同一查询级别上使用复杂表达式也是可行的替代方案。 - Lukasz Szozda
5个回答

75

你可以使用嵌套查询:

Select
  ColumnA,
  ColumnB,
  calccolumn1,
  calccolumn1 / ColumnC as calccolumn2
From (
  Select
    ColumnA,
    ColumnB,
    ColumnC,
    ColumnA + ColumnB As calccolumn1
  from t42
);

有一行数值为 3, 4, 5,其结果为:

   COLUMNA    COLUMNB CALCCOLUMN1 CALCCOLUMN2
---------- ---------- ----------- -----------
         3          4           7         1.4

如果第一次计算并未执行任何昂贵操作(例如函数调用),则可以直接重复使用第一次的计算结果:

Select
  ColumnA,
  ColumnB,
  ColumnA + ColumnB As calccolumn1,
  (ColumnA + ColumnB) / ColumnC As calccolumn2
from t42; 

   COLUMNA    COLUMNB CALCCOLUMN1 CALCCOLUMN2
---------- ---------- ----------- -----------
         3          4           7         1.4 

33

在 Sql Server 中

您可以使用 cross apply 来实现此操作。

Select
  ColumnA,
  ColumnB,
  c.calccolumn1 As calccolumn1,
  c.calccolumn1 / ColumnC As calccolumn2
from t42
cross apply (select (ColumnA + ColumnB) as calccolumn1) as c

17
如果您想引用“同一查询层级”上的计算列,则可以使用CROSS APPLY(Oracle 12c):
--Sample data:
CREATE TABLE tab(ColumnA NUMBER(10,2),ColumnB NUMBER(10,2),ColumnC NUMBER(10,2));

INSERT INTO tab(ColumnA, ColumnB, ColumnC) VALUES (2, 10, 2);
INSERT INTO tab(ColumnA, ColumnB, ColumnC) VALUES (3, 15, 6);
INSERT INTO tab(ColumnA, ColumnB, ColumnC) VALUES (7, 14, 3);
COMMIT;

查询:

SELECT
  ColumnA,
  ColumnB,
  sub.calccolumn1,
  sub.calccolumn1 / ColumnC AS calccolumn2
FROM tab t
CROSS APPLY (SELECT t.ColumnA + t.ColumnB AS calccolumn1 FROM dual) sub;

DBFiddle演示


请注意,来自CROSS APPLY/OUTER APPLY的表达式也可以在其他子句中使用:

SELECT
  ColumnA,
  ColumnB,
  sub.calccolumn1,
  sub.calccolumn1 / ColumnC AS calccolumn2
FROM tab t
CROSS APPLY (SELECT t.ColumnA + t.ColumnB AS calccolumn1 FROM dual) sub
WHERE sub.calccolumn1 = 12;
-- GROUP BY ...
-- ORDER BY ...;

这种方法可以避免将整个查询包装在外部查询中,也可以避免在多个地方复制/粘贴相同的表达式(对于复杂的表达式,可能难以维护)。
相关文章:SQL语言最缺失的功能

8

您需要在计算的列中包括表达式:

SELECT  
ColumnA,  
ColumnB,  
ColumnA + ColumnB AS calccolumn1  
(ColumnA + ColumnB) / ColumnC AS calccolumn2

或者您可以创建一个存储过程来输出列calcolumn1。 - swirlingsara
这只是先前答案的一部分副本。 - Mark Schultheiss

3
在SQL Server中,您可以使用With CTE来实现这一点。 使用 Common Table Expression (Transact-SQL)
CREATE TABLE tab(ColumnA DECIMAL(10,2), ColumnB DECIMAL(10,2), ColumnC DECIMAL(10,2))

INSERT INTO tab(ColumnA, ColumnB, ColumnC) VALUES (2, 10, 2),(3, 15, 6),(7, 14, 3)

WITH tab_CTE (ColumnA, ColumnB, ColumnC,calccolumn1)  
AS  
(  
Select
    ColumnA,
    ColumnB,
    ColumnC,
    ColumnA + ColumnB As calccolumn1
  from tab
)  

SELECT
  ColumnA,
  ColumnB,
  calccolumn1,
  calccolumn1 / ColumnC AS calccolumn2
FROM  tab_CTE

DBFiddle演示


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接