質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Oracle

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

4回答

7961閲覧

【ORACLE SQL】DECODEについて

programer

総合スコア31

Oracle

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

1クリップ

投稿2016/09/15 05:01

DECODEの条件分けについて質問させていただきたいです。
DECODEで条件分けした結果によって分岐して発行するSELECT文を分けてデータを取得したいです。

条件によってSELECT文を分けてそれぞれ違うテーブルからデータを取得したいです。

DECODEの結果の部分にSELECT文を入れ子のようにして
DECODE(AAA, 1,(SELECT~FROM TBL1)2,(SELECT~FROM TBL2))
のようにすることは可能なのでしょうか。

試してみたところ、できそうではあったのですが、このDECODEをする際のSELECT文での取得項目をどのようにすればよいか悩んでいます。
DECODEで取得される項目をすべて列挙すればよいのでしょうか。

SQL

1 2SELECT 3BBB, 4CCC, 5DDD, 6EEE, 7DECODE(AAA, 1,(SELECT BBB, CCC FROM TBL2), 2,(SELECT DDD, EEE FROM TBL3)) 8FROM 9TBL1 10

試したSQLを簡略化したものを記述してみましたが、DECODE内のSELECT分の箇所で値の数が多すぎますというエラーが出てしまいました。

このようなことをやりたい場合、
どのように修正すればいいのでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

雰囲気的に T1/T2/T3 を関係づけるキーがあるっぽいんで
そういう場合はこんな感じで

SQL

1select 2 DECODE(T1.AAA,1,T2.BBB,2,NULL) AS BBB, 3 DECODE(T1.AAA,1,T2.CCC,2,NULL) AS CCC, 4 DECODE(T1.AAA,1,NULL,2,T3.DDD) AS DDD, 5 DECODE(T1.AAA,1,NULL,2,T3.EEE) AS EEE 6from T1,T2,T3 7where T1.id=T2.id and T1.id=T3.id

なかったら… 忘れてください。(^_^;

投稿2016/09/15 10:59

takasima20

総合スコア7458

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

programer

2016/09/21 01:18

今回やりたいことはまさにこれでした。ありがとうございました!
guest

0

コードを見る限り、
テーブル1の1つのカラムの値に応じて、取得先を変えたいということですよね?

単一値を扱う組み込み関数は基本的に**インプットとアウトプットは共に単一値(複数カラムは不可、複数行返却もダメ)**なので、
DECODE関数では質問者さんのような使い方はできません。

そのためアプローチ方法を工夫する必要があります。

  1. DECODE関数にこだわって関数の使用方法に強引に合わせる
  2. そもそも発想を変えてみる

#頑張ってDECODEを利用
関数の利用ルールに合わせていくアプローチですが、
今回は複数カラムは返却できない、かつ複数レコードも取れないという縛りがあるため、

  • カラム同士の文字列結合する
  • 集約などを用いて取得レコード件数を1件とにする

少なくとも上記のような工夫が必要です。
個人的にはこちらのアプローチはしんどいですし、
エラーが解消したとしてもなかなか意図した結果が取れないという事態になりかねないと思います。

スマホからの回答でこちらのサンプルを書くのは少し手間なのでコードサンプルは割愛します。

#別の手段を模索する
折角SQLには

  • テーブル同士の結合
  • サブクエリの結果をさもテーブルみたいに扱える

という上記2点の強力な特性があるため、
これを使うに越したことはありません。
質問者さんのやりたいことをテーブル結合で実現するには、
0. TBL1と「TBL2、TBL3の和集合(UNION、UNION ALLしたもの)」を用意
0. 上記の和集合を作成する際にAAA列の値に対応する擬似列を設ける
0. TBL1と和集合をカラムAAAと和集合側で設けた擬似列とで結合する

恐らく上記のSTEPを踏めば実現できる、または近いことが行えるはずです。

こちらの考え方は身につけて貰えたら、割と役立つし応用も利くのでサンプルも記載しときます。

SQL

1SELECT 2 T1.* 3, T2.COL1 4, T2.COL2 5FROM 6 TBL1 T1 7 INNER JOIN ( 8 SELECT 9 1 AS JOIN_KEY 10 , BBB AS COL1 11 , CCC AS COL2 12 FROM 13 TBL2 14 UNION ALL 15 SELECT 16 2 AS JOIN_KEY 17 , DDD AS COL1 18 , EEE AS COL2 19 FROM 20 TBL3 21 ) T2 22 ON T1.AAA = T2.JOIN_KEY

投稿2016/09/15 09:40

Panzer_vor

総合スコア1636

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

programer

2016/09/21 01:22

DECODEで複数行の返却は不可能ということを初めて知りました。 別の手段を模索するの箇所で紹介していただいた考え方は今までしたことがない考えかたでした。 今回に関しては使用しませんでしたが、非常に勉強になりました。これはこれから使えそうなので、しっかりとサンプルを見させていただいて自分のものにしていきたいです。 そこで、質問なのですが、INNER JOINする際に使用している「JOIN_KEY」は実際にはどのようなものを指定すれば良いのでしょうか。 ほんとに1とか2でいいのでしょうか。
Panzer_vor

2016/09/21 03:30

> programerさん 結合キー用に作成したカラムの値やカラムの名称についてはケースバイケースです。 今回、質問者さんはT1のAAAのカラムが「1」の時にT2の値を取得、 T3の値が「2」の時にT3の値を取得したいということを行いたいようにお見受けしたので、 AAAの値とそれぞれのテーブルの関連を擬似的に作成するために今回のようなSQLとなってます。 別例をあげるとT1のAAAの値が「A」の時にT2を、「B」の時はT3のレコードと対応付けたい場合は、 結合用の疑似キーの値は、1や2でなく、「A」、「B」のようになります。
programer

2016/09/23 04:55

条件によって取得したいデータのテーブルが異なる場合、 候補候補となるテーブルのデータをUNIONして疑似キーの値によってUNIONしたデータの中から値を取得するということですね。
Panzer_vor

2016/09/23 13:18

> programerさん はい、その認識で問題ありません。 疑似キーはあくまで取得元を分類するために設ける手法となります。 こちらのやり方だと、TBL2、TBL3を同一カラムのデータとして表示することも、 別々のカラムとして表示することもできるため柔軟性があるので頭の片隅に入れて置いて損はないです。 またOracleを使っている限りは問題ないですが、 別ベンダのデータベースになるとDECODE関数は存在しないため、DBMSに依存しない書き方を覚えておくことは無駄なことではありません。 (DECODEがない場合はCASE式の利用が代替手段となりますかね・・・)
programer

2016/09/28 06:59

承知しました。 とても勉強になりました。 ありがとうございました。
guest

0

元質問者はいきなりコードを載せるだけではなく、何をやりたいのかを掲示板を読んでいる人が理解できるよう文章で書いてください。
DECODEの書き方は以下を参考に。
SQL言語リファレンス DECODE 例
shift-the-oracle DECODE

投稿2016/09/15 05:28

編集2016/09/15 06:42
Orlofsky

総合スコア16415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

今、手元にOracleの環境がないので試していませんが、

まず、SQL的に一つの列に1つの値を返すようにしないといけないので、
SELECT BBB, CCC FROM TBL2のように2列返すのはNGです。
ここは二つに分割しましょう。

そして、たとえば
SELECT BBB FROM TBL2
としてもこれが必ず1つの値を返すことをSQL文が保証していなければいけないので、
SELECT MAX(BBB) FROM TBL2
のように集約関数を使うなりしてください。

例えばこうなるでしょうか。

SQL

1DECODE(AAA, 1,(SELECT MAX(BBB) FROM TBL2), 2,(SELECT MAX(DDD) FROM TBL3)), 2DECODE(AAA, 1,(SELECT MAX(CCC) FROM TBL2), 2,(SELECT MAX(EEE) FROM TBL3))

投稿2016/09/15 05:13

dupont_kedama

総合スコア925

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

programer

2016/09/15 05:41

回答ありがとうございます。 これは取得したい項目が多ければ多いほどSQLが長くなってしまいそうですが、 このようなことをしたい場合、仕方がないということですよね?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問