如何在Oracle SQL语句中重用动态列?

我尝试重用一些我在Oracle SQL中动态计算的列,类似于

SELECT
    A*2 AS P,
    P+5 AS Q
FROM tablename

其中’tablename’有一个名为’A’的列,但没有其他列.这给了我一个

ORA-00904: "P": invalid identifier

我知道如何通过使用子查询来解决这个问题

SELECT P, P+5 AS Q
FROM ( SELECT A*2 AS P FROM tablename )

但我认为这有点难看.此外,我想使查询更复杂,例如重用’Q’,我不想创建另一个子查询.

更新:我想存储’P’计算的原因是我想让它更复杂,并多次重复使用’P’.所以我不想明确地说’A * 2 5 AS Q’,因为随着’P’越来越复杂,这很快会变得很麻烦.

必须有一个很好的方法来做到这一点,任何想法?

更新:我应该注意,我不是DB-admin :(.

更新:一个真实的例子,具有更具体的查询.我想做的是:

SELECT 
    SL/SQRT(AB) AS ALPHA,
    5*LOG(10,ALPHA) AS B,
    2.5*LOG(10,1-EXP(-5/ALPHA)*(5/ALPHA+1)) AS D
    BS -2.74 + B + D AS BSA
FROM tablename

现在,我已经把它写出来了,但是很难看:

SELECT
    SL/SQRT(AB) AS ALPHA,
    5*LOG(10,SL/SQRT(AB)) AS B,
    2.5*LOG(10,1-EXP(-5/(SL/SQRT(AB)))*(5/(SL/SQRT(AB))+1)) AS D
    BS -2.74 + 5*LOG(10,SL/SQRT(AB)) + 2.5*LOG(10,1-EXP(-5/(SL/SQRT(AB)))*((5/(SL/SQRT(AB)))+1)) AS BSA
FROM tablename

收到数据后我可以做所有这些,但我想,让我们看看我能让数据库做多少.另外,我也想选择“BSA”(我现在可以将此查询作为子查询/ with-clause).

更新:好的,我想现在我已经完成了Cade Roux和Dave Costa的解决方案.虽然Pax’和Jens Schauder的解决方案看起来会更好,但我不能使用它们,因为我不是DBA.现在我不知道谁将其标记为最佳答案:).

WITH 
  A1 AS ( 
    SELECT A0.*, 
    SL/SQRT(AB) AS ALPHA
    FROM tablename A0
  ),
  A2 AS (
    SELECT A1.*, 
    5*LOG(10,ALPHA) AS B,
    2.5*LOG(10,1-EXP(-5/ALPHA)*((5/ALPHA)+1)) AS D
    FROM A1
  )
SELECT
  ALPHA, B, D, BS,
  BS -2.74 + B + D AS BSA
FROM A2

顺便说一句,如果有人感兴趣,SB是星系的“表面亮度”,B和D是校正项.

最佳答案 我们在SQL Server中遇到同样的问题(这是一个ANSI问题).我相信它旨在避免混淆别名效果:

SELECT A * 2 AS A
    ,A * 3 AS B -- This is the original A, not the new A
FROM whatever

我们通过堆叠公用表表达式来解决它:

WITH A1 AS (
    SELECT A * 2 AS A
    FROM whatever
)
,A2 AS (
    SELECT A1.*
        ,A * 3 AS B
    FROM A1
)
,A3 AS (
    SELECT A2.*
        ,A + B AS X
    FROM A2
)
SELECT *
FROM A3

这是最易读,最易维护和可跟随的版本.

对于UPDATE,使用column_name = notation有一个不推荐使用的SQL Server变通方法,您可以在其中引用先前已在列表中更新的列.但这不能在SELECT中使用.

我希望将来某些时候可以在ANSI SQL中添加一些堆栈表达式(不使用标量UDF)的能力.

点赞