2009-04-13 2 views
4

나는Oracle SQL 문에서 동적 열을 다시 사용하는 방법은 무엇입니까?

SELECT 
    A*2 AS P, 
    P+5 AS Q 
FROM tablename 
'TABLENAME'는 'A'라는 열이

하지만, 다른 colums 같은 몇 가지 내가 오라클 SQL에서 동적으로 계산 열, 뭔가를 다시 사용하려고합니다. 이 날 내가

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

같은 하위 쿼리를 사용하여이 문제를 해결하는 방법을 알고

ORA-00904: "P": invalid identifier 

에게 제공하지만이 좀 추한 생각합니다. 또한 쿼리를 다소 복잡하게 만들고 싶습니다. 'Q'를 재사용하고, 또 다른 하위 쿼리를 만들고 싶지 않습니다.

업데이트 : 'P'계산을 저장하려는 이유는 더 복잡하게 만들고 'P'를 여러 번 사용하려는 것입니다. 그래서 나는 'A * 2 + 5 AS Q'라고 명시 적으로 말하고 싶지 않습니다. 왜냐하면 'P'가 더 복잡해지면 금방 성가 시게 될 것이기 때문입니다.

좋은 방법이 있어야합니다. 아이디어가 필요하십니까?

업데이트 : 나는 :(DB를-관리자 아니에요 있음을 유의


업데이트 :.. 실제 세계 예를 들어,보다 구체적인 쿼리 내가하고 싶은 무엇 것은 :

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 절로 사용할 수 있습니다.


업데이트 : 이제는 Cade Roux와 Dave Costa의 솔루션으로 끝났습니다. Pax '와 Jens Schauder의 솔루션은 더 좋아 보이지만 DBA가 아니기 때문에 사용할 수 없습니다. 지금 누가 가장 좋은 답으로 표시 할 지 모릅니다 :). 사람이 관심 경우 BTW


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에 대해 은하 '표면 밝기'이다.

답변

2

이 문제는 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 

이 가장 읽기 쉽고 maintable 및 followable 버전입니다.

UPDATE의 경우 이전에 목록에서 업데이트 된 열을 참조 할 수있는 column_name = 표기법을 사용하는 SQL Server 대안이 사용되지 않습니다. 그러나 이것은 SELECT에서 사용할 수 없습니다.

스칼라 UDF를 사용하지 않고 표현식을 스택하는 기능이 향후 어느 시점에서 ANSI SQL에 추가되기를 바랍니다.

+0

하하, 그것은 부작용을 일으켰습니다! 나는 처음에 'T'와 'S'를 사용했기 때문에 존재했던 새로운 칼럼에 사용되었습니다. 그래서 오류가 없었고, 단지 완전히 잘못된 값이었습니다. (200+ 열, 모두 2-5 자 ...) – BlackShift

+0

결과는 열 순서 변경에 따라 변하지 않습니다. 바라건대, ANSI는 일종의 인라인 스태킹 지시문 형태로 약간의 안도감을 제공 할 것입니다. –

0

나는이 작업을 수행 할 수 있는지 아니에요 (I 본 적이 그것을 수행)하지만 당신은 그것을 해결 수 : 확실히 하위 쿼리를 소개하는 것보다 더 나은

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

.

유일한 제안은 위의 수식을 사용하여 P/Q 유형 열을 제공하는보기를 작성하여 쿼리의 텍스트를 단순화하는 것입니다. 그렇다면 다음과 같이 할 수 있습니다.

SELECT P, Q FROM viewintotablename 
+0

예, 간단한 예제로 쿼리를 만들었습니다. 실제로 다른 값을 계산할 때 P 값을 여러 번 사용했습니다. P는 다소 복잡합니다. 나는 그 질문을 갱신 할 것이다. – BlackShift

+0

나는 당신이 쿼리에 대해 왜 그렇게 염려하는지 잘 모르겠습니다. 그들은 한 번 쓰여지는 경향이 있으므로 혼자 남겨 두는 경향이 있습니다. 그래서 그들은 정말로 "못생긴"것이 (정말로 추악한 것들이 적절하게 문서화되어 있다고 가정하면 :-) 중요하지 않습니다. – paxdiablo

+0

필자가 알고있는 유일한 DBA는 원시 속도 (raw speed)입니다. 비정규 화하지 않고 쉽게 수정할 수는 없을 것입니다 (예 : DB2에서 생성 된 열을 도입). – paxdiablo

0

수 없습니다.

이 하위 쿼리가 중첩 루프에서 재평가 될 것이다

(MERGE 힌트가 사용됩니다) : 당신은 하위 쿼리가 다시 평가하지 않으려면

, 서브 쿼리에 대한 NO_MERGE 힌트를 추가

SELECT /*+ LEADING(g) USE_NL(g, r) MERGE(g) */ 
     * 
FROM (
     SELECT 1 
     FROM dual 
     UNION ALL 
     SELECT 2 
     FROM dual 
     ) r, 
     (
     SELECT SYS_GUID() AS guid 
     FROM dual d 
     ) g 

--- 
33CA48C1AB6B4403808FB0219302CE43 
711BB04F9AFC406ABAEF8A8F4CFA1266 

이 하위 쿼리가 중첩 루프에서 재평가되지 않습니다 (NO_MERGE 힌트가 사용됩니다) :

SELECT /*+ LEADING(g) USE_NL(g, r) NO_MERGE(g) */ 
     * 
FROM (
     SELECT 1 
     FROM dual 
     UNION ALL 
     SELECT 2 
     FROM dual 
     ) r, 
     (
     SELECT SYS_GUID() AS guid 
     FROM dual d 
     ) g 

------ 
7715C69698A243C0B379E68ABB55C088 
7715C69698A243C0B379E68ABB55C088 

를 귀하의 경우, 강행에 t 쓰기 :

SELECT BS - 2.74 + d 
FROM (
     SELECT t2.*, 2.5 * LOG(10, 1 - EXP(-5/b)) * ((5/A) + 1) AS d 
     FROM (
       SELECT t1.*, 5 * LOG(10, alpha) AS b 
       FROM (
         SELECT /*+ NO_MERGE */ t.*, 
           SL/SQRT(AB) AS alpha 
         FROM tablename t 
         ) t1 
       ) t2 
     ) t3 

(EXPLOG는 비용이 많이 드는) 더 효율적입니다 및 디버그에 훨씬 더 쉽습니다.

+0

이 방법이 어떻게 적용되는지 잘 모르겠지만이를 명심하십시오. (재평가의 여부는 속도의 문제 일뿐입니다.) – BlackShift

0

SQL에서 직접 수행 할 수있는 방법은 없습니다.

그러나 PL/SQL을 사용하여 함수를 정의 할 수 있습니다. 그래서 P를 들어이

select 
    P(A), 
    Q(P(A)) 
from tablename 

과 같을 것이다 선택하고 Q이 원래 다음 (훨씬) 더 나은 아니라 기능이 복잡하고, 많은 매개 변수가없는 경우, 그것은 만들 수도 당신의 더 쉽게 읽을 수있는 문장.

또한 SQL 문과 모든 데이터와 독립적으로 함수를 테스트 할 수 있습니다.

+0

필자는 이전에 Oracle에서 기능을 만들지 않았으며 분명히 그렇게 할 수있는 충분한 권한이 없습니다. (나는이 쿼리를 자주 DB 와이드 함수를 보증 할만큼 충분히 필요로하지 않을 것이다.) – BlackShift

0

당신은 당신이 준 인라인 뷰의 예보다는이 조금 더 좋아 수 있습니다

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

그것은 똑같은 금액이지만 생각 읽기, 조금 더 명확합니다.

계산 된 열을 여러 열에서 사용하는 것이면 영구보기를 만드는 것이 좋습니다.

Oracle 11 (아직 사용하지 않음)에는 유용 ​​할 수있는 가상 열 기능이 있습니다.

+0

그게 더 읽기 쉽다. 나는 이것이 11g 데이터베이스라고 믿지만 DBA가 아니기 때문에 가상 컬럼에 있어야한다. – BlackShift

관련 문제