SQLでJOINするテーブルをカラムの値によって変えたい
解決済
回答 1
投稿
- 評価
- クリップ 0
- VIEW 681
前提
初めて質問させていただきます。
当方IT職ではなく、慣れませんが宜しくおねがいします。
例として以下のようなテーブルがあります。
FOOD_MENUにはご飯のメニューが入っています。
MENU_ID | NAME | (中略) | REQUIRED_FOOD1 | REQUIRED_FOOD2 | REQUIRED_FOOD3 |
---|---|---|---|---|---|
1 | カレー | ... | 201 | 202 | 301 |
2 | 焼肉 | ... | 301 | 302 | |
3 | 白米 | ... |
REQUIRED_FOOD1 と 2 と3には必要な食材のIDが格納されています。
VEGETABLE_FOODには野菜データが入っています。
FOOD_ID | NAME | PRICE |
---|---|---|
201 | じゃがいも | 100 |
202 | にんじん | 100 |
201 | たまねぎ | 80 |
野菜テーブルのFOOD_IDは必ず2で始まります。
MEAT_FOODにはお肉データが入っています。
FOOD_ID | NAME | PRICE |
---|---|---|
301 | 豚肉 | 300 |
302 | 牛肉 | 500 |
肉テーブルのFOOD_IDは必ず3で始まります。
実現したいこと
SQLでJOINするテーブルをカラムの値によって変えたいです。
具体的には、REQUIRED_FOODxの左端の値が2であればVEGETABLE_FOODテーブルをJOIN、3であればMEAT_FOODテーブルをJOINといった具合です。
しかし後述するクエリでは、私が求める結果が出ないのです。
試した事・ 発生している問題
以下のことを試しました。
LEFT JOINのテーブル名をCASE演算子で指定する
SELECT *
FROM FOOD_MENU
LEFT JOIN
(CASE LEFT(REQUIRED_FOOD1,1)
WHEN '2' THEN (VEGETABLE_FOOD AS VEGE1 ON FOOD_MENU.REQUIRED_FOOD1 = VEGE1.FOOD_ID)
WHEN '3' THEN (MEAT_FOOD AS MEAT1 ON FOOD_MENU.REQUIRED_FOOD1 = MEAT1.FOOD_ID)
END)
LEFT JOIN
(CASE LEFT(REQUIRED_FOOD2,1)
WHEN '2' THEN (VEGETABLE_FOOD AS VEGE2 ON FOOD_MENU.REQUIRED_FOOD2 = VEGE2.FOOD_ID)
WHEN '3' THEN (MEAT_FOOD AS MEAT2 ON FOOD_MENU.REQUIRED_FOOD2 = MEAT2.FOOD_ID)
END)
LEFT JOIN...(以下REQUIRED_FOOD3も同じようにJOIN)
結果:
[IBM]SQL0104 - トークン(は正しくない。有効なトークンはTO OUTER EXCEPTIONです。
エラーメッセージが帰ってきました。
必要なテーブルをすべてLEFT JOINする
SELECT *
FROM PEPOLE
LEFT JOIN VEGETABLE_FOOD AS VEGE1 ON FOOD_MENU.MENU_ID = VEGE1.FOOD_ID
LEFT JOIN MEAT_FOOD AS MEAT1 ON FOOD_MENU.MENU_ID = MEAT1.FOOD_ID
LEFT JOIN VEGETABLE_FOOD AS VEGE2 ON FOOD_MENU.MENU_ID = VEGE2.FOOD_ID
LEFT JOIN MEAT_FOOD AS MEAT2 ON FOOD_MENU.MENU_ID = MEAT2.FOOD_ID
LEFT JOIN .....(以下REQUIRED_FOOD3も同じようにJOIN)
結果:
MENU_ID | NAME | (中略) | VEGE1.NAME | MEAT1.NAME | VEGE2.NAME | MEAT2.NAME | VEGE3.NAME | MEAT3.NAME |
---|---|---|---|---|---|---|---|---|
1 | カレー | ... | じゃがいも | にんじん | ||||
1 | カレー | ... | 豚肉 | |||||
2 | 焼肉 | ... | 豚肉 | 牛肉 | ||||
3 | 白米 | ... |
結果は出るが、1行目と2行目を一緒にしたい。(後述)
理想
MENU_ID | NAME | (中略) | VEGE1.NAME | MEAT1.NAME | VEGE2.NAME | MEAT2.NAME | VEGE3.NAME | MEAT3.NAME |
---|---|---|---|---|---|---|---|---|
1 | カレー | ... | じゃがいも | にんじん | 豚肉 | |||
2 | 焼肉 | ... | 豚肉 | 牛肉 | ||||
3 | 白米 | ... |
MENU_IDを重複させずに、JOINしたテーブルの値も一つのレコードに集めたい(マージさせる?)
言い方が拙くて本当に申し訳ないのですがご教授ください。
補足情報(FW/ツールのバージョンなど)
IBM DB2 VER 9.7
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
SQLでJOINするテーブルをカラムの値によって変えたいです。
動的にSQLを組み立てない限りできません。
SQLの基本は集合を作成する事です。ケースがあるなら先ず全ての場合を含んだ集合を作ること。
WITH式で纏めて、それを結合
with FOOD as (
slect * from VEGETABLE_FOOD
union all
slect * from MEAT_FOOD
)
SELECT MENU.*, FOOD1.NAME, FOOD2.NAME, FOOD3.NAME
FROM FOOD_MENU AS MENU
LEFT JOIN FOOD AS FOOD1 ON MENU.REQUIRED_FOOD1= FOOD1.FOOD_ID
LEFT JOIN FOOD AS FOOD2 ON MENU.REQUIRED_FOOD2= FOOD2.FOOD_ID
LEFT JOIN FOOD AS FOOD3 ON MENU.REQUIRED_FOOD3= FOOD3.FOOD_ID
相関副問合せで行う。
FOOD_MENU の件数が少なければ(where条件で絞り込まれる場合も含む)こちらの方が高速。
SELECT MENU.*
, coalesce(
(select NAME from VEGETABLE_FOOD where FOOD_ID=MENU.REQUIRED_FOOD1)
,(select NAME from MEAT_FOOD where FOOD_ID=MENU.REQUIRED_FOOD1)
) FOOD1_NAME
, coalesce(
(select NAME from VEGETABLE_FOOD where FOOD_ID=MENU.REQUIRED_FOOD2)
,(select NAME from MEAT_FOOD where FOOD_ID=MENU.REQUIRED_FOOD2)
) FOOD2_NAME
, coalesce(
(select NAME from VEGETABLE_FOOD where FOOD_ID=MENU.REQUIRED_FOOD3)
,(select NAME from MEAT_FOOD where FOOD_ID=MENU.REQUIRED_FOOD3)
) FOOD3_NAME
FROM FOOD_MENU AS MENU
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.37%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
hihijiji
2019/06/08 13:49
まずは、データベースの正規化を行うことをお勧めします。
このままではどんどん酷いことになります。
TonToroJP
2019/06/08 14:46
ご指摘ありがとうございます。
権限はありませんが正規化についても調べてみようと思います。