2016-03-22 24 views
0

エラー:column ambiguous defined。 なぜ動作しないのですか? はここのコードです:列が曖昧に選択された場合、oracleを持つ結合から選択した場合

SELECT SL.id, 
     SL.sn, 
     SL.title, 
     CASE 
     WHEN SL.sn IS NOT NULL THEN PRL.start_date 
     ELSE SL.start_date 
     END AS start_date, 
     CASE 
     WHEN SL.sn IS NOT NULL THEN PRL.end_date 
     ELSE NULL 
     END AS end_date, 
     SL.father_id, 
     SL.sn, 
     SL.project, 
     SL.username, 
     SL.RUN, 
     SL.zip_path, 
     SL.log_file 
FROM scheduler_list SL 
     left join package_running_list PRL 
       ON SL.sn = PRL.sn 
HAVING start_date >= To_date('2016-02-28', 'YYYY-MM-DD') 
     AND (end_date <= To_date('2016-04-10', 'YYYY-MM-DD') + 1 
       OR end_date IS NULL) 
+2

テーブルSLとPRLには開始日と終了日があります。あなたはhaving句で使用しているものを指定する必要があるかもしれません。 – SriniV

+1

なぜそれが混乱しますか?あなたのコードはPRL.start_dateとSL.start_dateを持っていることを示しているので、あなたが意味するものを指定するために 'having'節にあるものを修飾する必要があります。 case文のために作成しているエイリアスを参照しようとしている場合、そのことはできません。あなたはまた、having節を持つグループバイを持っていません。 –

+0

OK、どうすればいいですか?@AlexPoole?私はあなたが取るべきものを決めるためにそこに必要がある... – Mojo

答えて

1

start_dateend_dateの使用はPRLSLテーブル間の曖昧にならないようにあなたは、外側の選択にHAVING句を移動することができます。このように:

SELECT * 
FROM (
    SELECT SL.id, 
     SL.sn, 
     SL.title, 
     CASE 
      WHEN SL.sn IS NOT NULL THEN PRL.start_date 
      ELSE SL.start_date 
     END AS start_date, 
     CASE 
      WHEN SL.sn IS NOT NULL THEN PRL.end_date 
      ELSE NULL 
     END AS end_date, 
     SL.father_id, 
     SL.sn AS sn1,  -- DUPLICATE COLUMN 
     SL.project, 
     SL.username, 
     SL.RUN, 
     SL.zip_path, 
     SL.log_file 
    FROM scheduler_list SL 
     left join package_running_list PRL 
       ON SL.sn = PRL.sn 
) 
WHERE start_date >= DATE '2016-02-28' 
     AND (end_date <= DATE '2016-04-11' OR end_date IS NULL) 
+0

は既に 'where'ステートメントを試したが、それでも同じエラーで失敗する – Mojo

+0

' SELECT'を( 'WHERE' /' HAVING'節なしで)ラップしようとしましたか? 'SELECT'を実行してその外側の' SELECT'に 'WHERE'文を追加しますか?(上の例のように) – MT0

+0

同じ問題です.. – Mojo

1

あなたのコードは、あなたがPRL.start_dateSL.start_dateを持って示して、あなたはあなたが意味するかを指定するhaving句に1を修飾する必要があります - あなたはPRLまたはSLから値をするかどうか。表修飾子を指定しないと、Oracleは参照している表の列を認識しません。エラー・メッセージに示されているように、あいまいです。

しかし、おそらく元のテーブルの列を必要とせず、case文のために作成する列エイリアスを参照しようとしているようです。あなたはそれをすることはできません。それらが定義されているとして、それがin the documentationを言うように列の別名は、order by句を除き、クエリの同じレベルで使用することはできません。

c_aliasで
列式の別名を指定します。 Oracle Databaseは、このエイリアスを結果セットの列見出しに使用します。 ASキーワードはオプションです。エイリアスは、クエリの期間中、選択リスト項目の名前を変更します。エイリアスは、order_by_clauseでは使用できますが、クエリ内の他の句は使用できません。あなたはcase文繰り返すのいずれかになります

WHERE CASE 
    WHEN SL.sn IS NOT NULL THEN PRL.start_date 
    ELSE SL.start_date 
    END >= To_date('2016-02-28', 'YYYY-MM-DD') 
    AND (CASE 
      WHEN SL.sn IS NOT NULL THEN PRL.end_date 
      ELSE NULL 
     END <= To_date('2016-04-10', 'YYYY-MM-DD') + 1 
      OR CASE 
      WHEN SL.sn IS NOT NULL THEN PRL.end_date 
      ELSE NULL 
     END IS NULL) 

を(あなたがグループ・バイ節を持っていないので、havingは本当にここに意味をなさないので、私はそれを変更しましたwhere)、

または副問合せを使用する/ CTE /インライン・ビュー:

SELECT * FROM (
    SELECT SL.id, 
     SL.sn, 
     SL.title, 
     CASE 
      WHEN SL.sn IS NOT NULL THEN PRL.start_date 
      ELSE SL.start_date 
     END AS start_date, 
     CASE 
      WHEN SL.sn IS NOT NULL THEN PRL.end_date 
      ELSE NULL 
     END AS end_date, 
     SL.father_id, 
     SL.project, 
     SL.username, 
     SL.RUN, 
     SL.zip_path, 
     SL.log_file 
    FROM scheduler_list SL 
     left join package_running_list PRL 
       ON SL.sn = PRL.sn 
) 
WHERE start_date >= To_date('2016-02-28', 'YYYY-MM-DD') 
     AND (end_date <= To_date('2016-04-10', 'YYYY-MM-DD') + 1 
       OR end_date IS NULL) 

モス元のクエリのtがインラインビューに移動しました。インラインビューは、2つのベーステーブルを参照し、あいまいさがありません。その内側のクエリを独自に実行すると、それが動作することがわかりますが、必要以上のデータが返されます。

SL.snへの重複参照を削除するように内部クエリを変更しました。そのビューを2回実行すると、同じ名前の2つの列を持つビューと同じORA-00918が発生します。なんらかの理由で2回使用したい場合は、*を使用する代わりに外側の選択項目に列をリストし、それを繰り返してください。または内側のクエリに複製を保持しますが、別名を使用するようにエイリアスを使用します。私はそれが偶然だったと思う。

外側のwhere句のstart_dateend_dateの結果は、内側のクエリのcase式の結果です。これにより、短くて読みやすく、保守が簡単なケースロジックを繰り返すことがなくなります。ロジックが変更された場合は、2つまたは3つではなく、1つの場所で変更するだけです。

外部クエリでは、内部クエリで使用する基本テーブルまたはそのエイリアスPRLおよびSLを表示できません。その内部問合せからの結果セットしか見ることができず、結果セットの列名にあいまいさはありません。


の質問に関係のない、あなただけ簡潔にするために、ANSI日付リテラルを使用して検討する必要があります:のみ固定リテラルで動作します

WHERE start_date >= DATE '2016-02-28' 
     AND (end_date IS NULL OR end_date <= DATE '2016-04-10' + 1) 

けれども。 +1は実際のコードが日付に変換する文字列を渡されていることを示唆しています。この場合、to_date()を使用する必要があります。そして最後の比較は<=ではなく<であることを意図しているかもしれませんが、伝えるのは難しいでしょう。

+0

はすでに 'where'ステートメントを試していますが、同じエラーで失敗します。 – Mojo

+0

@mojo - ' start'dateを修飾しないと、同じレベルのクエリーで 'where'を使用してもエラーは発生します何を意味するのかを言う。 'having'を' where'に変更することはできません。case文を繰り返すか、読みやすく、反復回数が少なくてメンテナンスが簡単なサブクエリを使用する必要があります。 –

+0

アレックスを助けてくれてありがとうが、私はそれを手に入れないのですみません。 start_dateを 'case'ステートメントの結果としてqulifyできますか?私がそれをやり遂げることができないなら、私は何ができますか? – Mojo