- ベストアンサー
SQLの質問
会計のデータベースを作成していて、上司から セレクト文において下記のようなSQL文を理解せよと言われたのですが、 C1.FINANCEPOINT_C(+) = A.FEEPOINT_C の (+)にはどのような効果が、 あと、同じテーブルをB1、B2など分けるのはどのような 利点があるのでしょうか。 ネットや本でも、合致するものがなかなか探せないでいます。 よろしくおねがいたします。 SELECT A.TOTALNO ,A.RENTALPART_C ,B2.RENTALPART ,A.RENTALPOINT_C ,C2.RENTALPOINT ,A.RENTALHELP ,D2.RENTALHELP ,A.FEEPART ,B1.FEEPART ,A.FEEPOINT_C ,C1.FEEPOINT ,A.FEEHELP_C ,D1.FEEHELP ,A.DAY ,A.TIME FROM HELP_DATA D2,HELP_DATA D1 ,POINT_DATA_C2,POINT_DATA C1 ,PART_DATA B2,PART_DATA B1 ,DETAIL A WHERE C2.FINANCEPOINT_C(+) = A.RENTALPOINT__C AND C1.FINANCEPOINT_C(+) = A.FEEPOINT_C AND D2.FINANCEHELP_C(+) = A.RENTALHELP_C AND D1.FINANCEHELP_C(+) = A.FEEHELP_C AND B2.FINANCEPART_C(+) = A.RENTALPART_C AND B1.FINANCEPART_C(+) = A.FEEPART_C AND A.TOTALCODE = '22222' AND A.PRIVATE = '1111'
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
例題が理解を阻んでいる気がしますね・・・ 簡単な例で説明します。 (+)とは外部結合。つまり空集合との結合を許すことです。 例: ○テーブル名:果物 △列名:名前,産地 りんご,青森 みかん,静岡 バナナ,フィリピン ○テーブル名:単価 △列名:名前,値段 りんご,100円 バナナ,80円 ここで、果物と単価テーブルを使用して、名前ごとの値段を表示したい場合があるとします。ただし、名前は全て表示したい。 上記の条件を満たそうとすると、単純に名前で結合することが出来ません。 なぜなら、単価テーブルには「みかん」の情報が無いため、「みかん」が表示されなくなってしまうためです。 ここで外部結合を使用すると、上手に結果を取得することができます。 select 果物.名前,単価.値段 from 果物、単価 where 単価.名前(+) = 果物.名前 このSQLは単価テーブルに結合対象データがなくても、空のレコード(空集合)と結合しろ!という意味になります。 そして結果は りんご、100円 みかん、null バナナ、80円 となります。 次に、1テーブルを別名で結合する件ですが、 1つの元のとなるレコードに対し、複数のレコードが存在するが、 これを1レコードで表示したい場合などに使用されます。 つまり、行を列に変換する。 これも、簡単な例題を用いたほうがわかりやすいでしょう。 外部結合で使用したテーブル以外に下記のテーブルを用意します。 ○テーブル名:果物属性 △列名:名前、属性名、属性値 りんご、色、赤 りんご、重さ、200g みかん、色、オレンジ みかん、重さ、100g 上記の果物属性テーブルと果物テーブルから、「名前」ごとに「産地」、「色」、「重さ」を取得したい場合。ただし、「名前」1種類に対して1レコードで表示したい場合。(行を列に変換したい) 単純に「名前」だけで結合すると、「色」と「重さ」が2レコードに分かれているので、「名前」ごとに2レコード出力されてしまいます。 ここで果物属性テーブルを別名で使い分けることで解決することが出来ます。 select 果物.名前,果物.産地,color.属性値 AS '果物の色' ,wight.属性値 AS '果物の重さ' from 果物、果物属性 AS color,果物属性 AS wight where 果物.名前 = color.名前 and color.属性 = '色' and 果物.名前 = wight.名前 and wight.属性 = '重さ'; 結果は りんご、青森、赤、200g みかん、静岡、オレンジ、100g となります。 2レコードに分かれて登録されていた「色」、「重さ」が1レコードで表示されました。 つまり、行が列に変換されました。
その他の回答 (3)
- jhayashi
- ベストアンサー率29% (535/1843)
う~ん 言葉で説明 わかりにくいですよね(^^; 上記テーブルをさらに簡略化して データが A.NO,A.R_C,A.F_C 1,10,10 2,20,30 3,30,40 B.C,B.NAME 10,AAA 30,BBB として その1(なんか結果が少ない・・・) select A.NO,A.R_C,B1.NAME,A.F_C,B2.NAME from A,B B1,B B2 where A.R_C = B1.C and A.F_C = B2.C; 結果 1,10,AAA,10,AAA その2(やりたいのってこれ?) select A.NO,A.R_C,B1.NAME,A.F_C,B2.NAME from A,B B1,B B2 where A.R_C = B1.C(+) and A.F_C = B2.C(+); 結果 1,10,AAA,10,AAA 2,20,(null),30,BBB 3,30,BBB,40,(null) その3(あれ?名前がでないよだめじゃん) select A.NO,A.R_C,B.NAME,A.F_C,B.NAME from A,B where A.R_C = B.C(+) and A.F_C = B.C(+); 結果 1,10,AAA,10,AAA 2,20,(null),30,(null) 3,30,(null),40,(null) 説明になっているようななっていないような こんなんで伝わるかな
お礼
だいぶ、違いが分かりました。 その1 やはり、where A.R_C = B1.C and A.F_C = B2.C; のような、時は、A.R_C と A.F_C の値が一致していないものについ ては選択されていませんね~。 その2、確かに、よく外部結合についてがつかめてきました。 片方が、そろっていれば、残っていますし、両方条件に合致するもの は、複数出てきても、1つとして表示されるんですねー。 また、(+)がついていないほうを、基準として、(+)がついている 方をくっつける、というイメージで(+)ついていないほうの項目を 優先させるということでよいでしょうか。 その3、確かに、違いが明確にでましたね。一致しているものと、 逆に両方一致していないものが残って結合したという感じですね。 もう少し、ためしてみて、つかんでみたいと思います。ありがとうございました。
- jhayashi
- ベストアンサー率29% (535/1843)
(+)は外部結合のしるしなんで oracleの本じゃなければ outer join の項目を参照すればいいですね。 同じテーブルをB1、B2など分けるのはどのような 利点があるのでしょうか。 上記SQLだと DETAILのFEEPART_Cに対するFEEPARTと DETAILのRENTALPART_Cに対するRENTALPART を表示したいので B1って別名をつけたテーブル、B2と別名をつけたテーブルからそれぞれ 取得しています もし上記SQLで別名をつけなければ FEEPART_CとRENTALPART_Cの値が一致しているときしかFEEPART、RENTALPARTが表示されないですよ
お礼
ありがとうございます。外部結合ということは、 B2.FINANCEPART_C(+) = A.RENTALPART_C でいえば、B2と、Aを結合して、FINANCEPART_CとRENTALPART_Cで値が一致する部分は一まとめに 値が一致しない部分はそれぞれとして、表示するという事ですね。 同じテーブルを別テーブルとして扱うということで、上記の B2.FINANCEPART_C(+) = A.RENTALPART_C と AND B1.FINANCEPART_C(+) = A.FEEPART_C の連関がなくなり、 A.RENTALPART_C に対する B2のRENTALPARTを、 A.FEEPART_C に対する、B1.FEEPARTをそれぞれ表示させることができる という事になりますか。ただ、ここではANDで結んでいるので、両方の 条件が満たされていないと表示されないかとは思いますが,ANDで結ばれ いない場合も、テーブル名を分けないと、A.RENTALPART_CとA.FEEPART_C の同一が必至になってくるという事でしょうか。 例題自体もちょっと、問題がある部分があるかもしれませんが、教えて いただきありがとうございます。
- chukenkenkou
- ベストアンサー率43% (833/1926)
「列名(+)=列名」は、外部結合を表すOracleの独自構文です。
お礼
本にもあまり載っていないのは独自構文だからなのですね。 ありがとうございました。
お礼
ありがとうございます。 >(+)とは外部結合。つまり空集合との結合を許すことです。 これで、大分、前がひらけました。 >ここで外部結合を使用すると、上手に結果を取得することができます。 >select 果物.名前,単価.値段 from 果物、単価 >where 単価.名前(+) = 果物.名前 >このSQLは単価テーブルに結合対象データがなくても、空のレコード(空集>合)と結合しろ!という意味になります。 ここに集約されておりますね。大分、便利な使い方ができるのが分かりました。 >上記の果物属性テーブルと果物テーブルから、「名前」ごとに「産地」、>「色」、「重さ」を取得したい場合。ただし、「名前」1種類に対して1レ>コードで表示したい場合。(行を列に変換したい) >単純に「名前」だけで結合すると、「色」と「重さ」が2レコードに分かれ>ているので、「名前」ごとに2レコード出力されてしまいます。 >ここで果物属性テーブルを別名で使い分けることで解決することが出来ま>す。 select 果物.名前,果物.産地,color.属性値 AS '果物の色' ,wight.属性値 AS '果物の重さ' from 果物、果物属性 AS color,果物属性 AS wight where 果物.名前 = color.名前 and color.属性 = '色' and 果物.名前 = wight.名前 and wight.属性 = '重さ'; > 確かに、結果をみると、見事に、重複が除かれ、行が列になって おりますね。複雑なので、何回も、反復して、理解してみたいと 思います。いかに簡単な例でも、理解しきれるかがポイントに なるのが分かりました。 ありがとうございました。もう少し、理解が深まりましたら、 改めて、お礼の書き込みをさせていただきます。