2009-04-13 8 views
4

私はOracleのSQL「テーブル名」が「A」という名前の列が、それ以外のcolumsを持ってOracle SQL文で動的列を再利用する方法は?

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

のようなもので、動的に計算するいくつかの列を再利用してみてください。これは私に

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管理者じゃないことに注意する必要があります:(


更新:。。現実世界の例では、より具体的なクエリで私は何をしたいことは次のとおりです。

今の
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節としてこのクエリを実行することができます)。


アップデート:OK、私は今、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は補正項であるため銀河、「の表面の明るさ」です。

答えて

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と追従可能バージョンです。

UPDATEの場合、以前にリストで更新された列を参照できるcolumn_name =表記法を使用して、非難されたSQL Serverの回避策があります。しかし、これはSELECTでは使用できません。

私は、スカラーUDFを使用せずに式をスタックする機能が将来、ANSI SQLに追加されることを期待しています。

+0

笑、それは副作用を引き起こしました!私が最初に新しい列に「T」と「S」を使用していたからです。エラーはなく、値はまったく間違っていました。 (200+列、すべて2〜5文字...) – BlackShift

+0

結果は、列順序の変更で不変であることを意味します。うまくいけば、ANSIはある種のインラインスタッキング命令の形でいくつかの救済策を提供するでしょう。 –

0

は、私はあなたがこれを行うことができますかわからない(私は見たことがない、それが行われる)が、あなたがそれを回避することができます:確かにサブクエリを導入するよりはましだ

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が気にすることがわかっている*唯一のことは、生の速度です。私はあなたが非正規化なしで簡単に修正できるとは思わない(つまり、生成された列をDB2に導入する)。 – paxdiablo

0

できません。

あなたがサブクエリのため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 
:この副問合せは、ネストされたループ( MERGEヒントが使用されている)に再評価されます

このサブクエリは、ネストされたループ(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 

トンの書き込み:

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とQの場合、この

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

ようになります。ステートメントははるかに読みやすい。

また、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

関連する問題