• 締切済み

ORACLE 効率の良いDB設計について

複合キーとはこういう時に使うのでしょうか? テーブルが2つあるとします。 テーブルAは、CODE テーブルBは、CODE1,CODE2,NAME とします。 テーブルAの"CODE"とテーブルBの"CODE1"+"CODE2"をキーに テーブルBの"NAME"を取得する場合。 たとえばテーブルAのCODEに"A1B1"という値が入っていて テーブルBのCODE1,CODE2の値にそれぞれ、"A1"、"B1"が入っている場合、テーブルBの主キーはCODE1とCODE2の二つにした方が効率がいいですか? select テーブルA.code,テーブルB.name from テーブルA,テーブルB where テーブルA.code = テーブルB.code1 || テーブルB.code2 ↑あっているかちょっと自信がないですが こういった処理をしたいと思っています。 よろしくお願い致します。

みんなの回答

  • jjon-com
  • ベストアンサー率61% (1599/2592)
回答No.1

code1の値が「NOT NULL かつ UNIQUE」すなわち「空値は存在せず,重複値も存在しない」と保証されるのであれば,テーブルBの主キー属性はcode1だけで十分です。code2を主キーに含めて複合キーにする必要はありません。 例えば,テーブルBの(code1, code2)の値の例として,   ('A1', 'B1')   ('A1', 'B2') のようなデータの存在を認めるならば,code1だけでは行を一意に識別できないから,(code1, code2)の複合キーを主キーとするわけです。複合キーでなくても,もしかするとcode2単独項目だけで主キーになるかもしれません。 もっと言うなら,テーブルBの(code1, code2, name)の値の例として,   ('A1', 'B1', 'rosary777')   ('A1', 'B1', 'rosary888') のようなデータの存在を認めるならば,(code1, code2)のペアでは行を一意に識別できないから,(code1, name)なり(code2, name)なり(code1, code2, name)なり,いずれかの複合キーを主キーとするわけです。データの取りうる条件がさらに提示されることで主キーの候補が絞られてくるかもしれません。 >テーブルBの主キーはCODE1とCODE2の二つにした方が効率がいいですか? 主キーを決める要因は効率ではありません。上記で説明したように,データによって必然的に決まってくるものです。 質問文では(CODE1,CODE2,NAME)という属性名と,('A1','B1')という値の一例が提示されているだけです。これをもとに「テーブルBの主キーをどれにするか」という問いに回答することは不可能です。

関連するQ&A

  • Oracle[10g]のSQL文について(改めて)

    すみません。[B]テーブルの作成がおかしい様でしたので、 改めて質問させて下さい。 Oracle[10g]のSQL文についての質問です。(No.???) [A]テーブルに [CODE](KEY) [CODE2] [NAME] のフィールドがあります。 A-1 B-1 NAME-1 A-2 B-2 NAME-2 A-3 B-3 NAME-3 [B]テーブルに [CODE3](KEY) [NAMEB] のフィールドがあります。 B-1 NAME-B-1 B-2 NAME-B-2 [C1]テーブルに [NO](KEY) [LINE](KEY) [CODE] のフィールドがあります。 X 1 A-1 X 2 A-3 Y 1 A-2 結果が [NO/LINE/CODE/NAMEB] X 1 A-1 NAME-B-1 X 2 A-3 (NULL) と、なる様にしたいのです。 SELECT C1.NO, C1.LINE,C1.CODE, Tx.NAMEB FROM C1 , ( SELECT C1.CODE, TNMx1.NAMEB FROM C1, ( SELECT CODE, CODE2, CODE3, NAMEB FROM A, B WHERE A.CODE2 = B.CODE3 ) TNMx1 WHERE C1.NO = 'X' AND C1.CODE = TNMx1.CODE(+) ) Tx WHERE C1.NO = 'X' GROUP BY C1.NO, C1.LINE,C1.CODE, Tx.NAMEB と、考えたのですが、何故か結果が X 1 A-1 (NULL) X 1 A-1 NAME-B-1 X 2 A-3 (NULL) X 2 A-3 NAME-B-1 4行もでてしまいます。 問題は、[B]テーブルです。 宜しくお願い致します。

  • SELECTのスピード

    SELECTのスピードでどの方法が 検索スピードが速いのか教えてもらいたいのですが Aのテーブル DENNO CODE Bのテーブル CODE NAME Aのテーブルを主にAのCODEでBのテーブルを参照したい時 (1) SELECT A.DENNO,A.CODE, (SELECT B.NAME from B where A.CODE=B.CODE) AS NAME from A (2) SELECT A.DENNO,A.CODE,B.NAME FROM A LEFT JOIN B ON A.CODE=B.CODE (3) SELECT A.DENNO,A.CODE,B.NAME FROM A , B WHERE A.CODE=B.CODE(+)

  • 効率のいい集計SQL文

    プログラム勉強中の者です・・・ 効率のいいSQL文が書けずに困ってます・・。 みなさまどうかお助け下さい。m(_ _)m 以下のテーブルにおいて、 TABLE:SAMPLE ※主キー:CODE+PM | CODE| PM |PROFIT| ――――――――――― |  101 |  + |  200 | |  102 |  + |  300 | |  103 |  + |  400 | |  101 |  - |  100 | |  102 |  - |  200 | |  103 |  - |  300 | 「PROFIT」を「CODE」で集計する。 但し、「PM」が「+」の場合は加算「-」の場合は減算する。 で以下の様な結果を得たい、という要件です。 | CODE | PROFIT | ――――――――― |  101 |   100 | |  102 |   100 | |  103 |   100 | 私が考えた方法は SELECT CODE,SUM(PROFIT) FROM SAMPLE GROUP BY CODE として抽出したレコードをループさせて SELECT PROFIT FROM SAMPLE WHERE CODE = (ループ処理中のCODE) AND   PM = "-" の結果の2倍の値を減算していく、というモノなんですが、 これがとっても効率が悪く、データ量が増えると加速度的に 遅くなるのです。 1回のSQLで処理する方法、または もっと効率の良いロジックは無いでしょうか・・・ ちなみに環境はoracle9i+VB6です。 たぶん初歩的な事だと思うんですが、学習書やWebで調べる限りは うまい解決方が見つかりませんでした・・・。

  • 【初歩的な質問ですが・・・】 SQL文書き方がわかりません

    SQLの知識に乏しい者です。 よろしくお願い致します。 ●テーブルA ・会計コード ・年度 ・部署番号 ・社員番号 ・その他幾つかのデータ ※Where句で「年度>2002年」以降を抽出 のテーブルがあります。 この時、Bテーブルで ●テーブルB ・会計コード(主キー) ・年度 ・部署番号(主キー) ・社員番号(主キー) ・その他幾つかのデータ ※Aテーブルで抽出されたデータの中から絞り込む というテーブルを抽出するSQL文を組みたいのですが、効率の良いやり方がわかりません。 副問合せで  Select [B表で抽出した列名…]  From B表  Where 会計コード = (Select 会計コード               From A表               Where 年度 > '2002')  AND 部署番号 = (Select 部署番号             From A表               Where 年度 > '2002') ・・・・以下省略 の様に書くと効率が悪い気がしました。 (実際には、副問合せが6個書くことになるため) 良い書き方を知っている方がいらっしゃいましたら、よろしくお願い致します。

  • テーブル参照について

    お世話になります。 AテーブルとBテーブルを比較し、Aテーブルにしかないデータ一覧を表示するSQL文を作成しました。 SELECT * FROM Aテーブル WHERE NOT EXISTS(SELECT * FROM Bテーブル WHERE CODE=Aテーブル.CODE AND NAME=Bテーブル.NAME) 下記の場合はどのように記述すればいいのでしょうか? 検索結果はAテーブルに存在しているが、BテーブルまたはCテーブルには存在していないデータ。 以上よろしくお願いいたします。

  • Oracl[10g]の SQL文について(No.7)

    何度も恐縮です。また、違った事が出てきました。(^^; 皆様にとっては、似たような事ばかりかと思いますが・・・ Oracl[10g]の SQL文について、教えて下さい。 [A]テーブルに [CODE](key) と [NAME]フィールドがあるとします。 内容は、 A-1 NAME-1 A-2 NAME-2 A-3 NAME-3 と、します。 [A2]テーブルに[NO](key) [CODE1] と [CODE2] と [CODE3]フィールドがあるとします。 内容は、 1 A-1 A-2 (null) 2 A-2 A-1 A-3 3 (null)A-3 A-2 と、します。 結果が、 1 A-1 NAME-1 A-2 NAME-2 (null) (null) 2 A-2 NAME-2 A-1 NAME-1 A-3 NAME-3 3 (null/null)A-3 NAME-3 A-2 NAME-2 と、なる様にする為には、どういうSQL文を書けば良いのでしょうか ? SELECT A1x.CODE1,A.NAME,A2x.CODE2, A.NAME,A3x.CODE3, A.NAME FROM A, (SELECT A.CODE, A.NAME, A2.CODE1 FROM A,A2 WHERE A.CODE=A2.CODE1 GROUP BY A.CODE,A.NAME,A2.CODE1) A1x, (SELECT A.CODE, A.NAME, A2.CODE2 FROM A,A2 WHERE A.CODE=A2.CODE2 GROUP BY A.CODE,A.NAME,A2.CODE2) A2x, (SELECT A.CODE, A.NAME, A2.CODE3 FROM A,A2 WHERE A.CODE=A2.CODE3 GROUP BY A.CODE,A.NAME,A2.CODE3) A3x WHERE A.CODE=A1x.CODE1 AND A.CODE=A2x.CODE2 AND A.CODE=A3x.CODE3 と、自分でチャレンジしたのですが、何も出てきません。 よろしくお願い致します。

  • 複数のPKを持つテーブル同士の結合について

    以下のような2つのPKを持つテーブル同士で、お互いに存在しないPKのデータを抽出するときのSQLを教えて下さい。 以下のデータの場合、テーブルAではCODE_1がAAAAAのデータ、テーブルBではCODE_1がCCCCCのデータのことを指します。 [テーブルA] CODE_1 CODE_2 ----- --- AAAAA 123 BBBBB 123 [テーブルB] CODE_1 CODE_2 ----- --- BBBBB 123 CCCCC 123 PKがCODE_1だけの場合は、 select distinct テーブルA.CODE_1 from テーブルA,テーブルB where テーブルA.CODE_1 not in ( select テーブルA.CODE_1 from テーブルA,テーブルB where テーブルA.CODE_1 = テーブルB.CODE_1) で、AAAAAが抽出できるとこまでは分かったんですが、複数のPKになったらいきなり分からなくなってしまいました。 どうかよろしくお願いします。

  • Oracl[10g]の SQL文について(No.8)

    何度も恐縮です。前回の質問の続きとなるかと思いますが・・・ Oracl[10g]の SQL文について、教えて下さい。 [A]テーブルに [CODE](key) と [NAME]フィールドがあるとします。 内容は、 A-1 NAME-1 A-2 NAME-2 A-3 NAME-3 と、します。 [A2]テーブルに[NO](key) [CODE1] と [CODE2] と [CODE3]フィールドがあるとします。 内容は、 1 A-1 A-2 (null) 2 A-2 A-1 A-3 3 (null)A-3 A-2 と、します。 結果が、 1 A-1 NAME-1 A-2 NAME-2 (null) (null) 2 A-2 NAME-2 A-1 NAME-1 A-3 NAME-3 3 (null/null)A-3 NAME-3 A-2 NAME-2 と、なる様にする為のSQL文は、 >select a2.no, a2.code1,a_1.name, a2.code2,a_2.name, a2.code3,a_3.name >from a2, >(select code, name from a) a_1, >(select code, name from a) a_2, >(select code, name from a) a_3 >where >a2.code1 = a_1.code(+) and >a2.code2 = a_2.code(+) and >a2.code3 = a_3.code(+) と、教えて頂き、完成致しました。 これを、アレンジして、 SELECT A2.NO, A2x.N1, A2x.N2, A2x.N3 FROM A,A2 , ( select a2.no, a2.code1,a1x.name AS N1, a2.code2,a2x.name AS N2, a2.code3,a3x.name AS N3 from a2, (select code, name from a) a1x, (select code, name from a) a2x, (select code, name from a) a3x where a2.code1 = a1x.code(+) and a2.code2 = a2x.code(+) and a2.code3 = a3x.code(+) ) A2x WHERE A2.NO='1' GROUP BY A2.NO, A2x.N1, A2x.N2, A2x.N3 ORDER BY A2.NO と、作りました。つまり、 1 A-1 NAME-1 A-2 NAME-2 (null) (null) と、言う結果が欲しいのです。 ところが、 1 (null) NAME-3 NAME-2 1 NAME-1 NAME-2 (null) 1 NAME-2 NAME-2 NAME-3 と、3行も出てしまいます。 よろしくお願い致します。

  • Oracle[10g]のSQL文について。(新No.3)

    なんども、恐縮です。 Oracle[10g]のSQL文についての質問です。(新No.3) 実は、JOINが多くてどこに[ROW_NUMBER]を入れれば良いのか解りません。 [A]テーブルに [CODE](KEY) [CODE2] のフィールドがあります。 A-1 B-1 A-2 B-2 A-3 B-3 [A2]テーブルに [CODEB](KEY) [CODE2] のフィールドがあります。 AA-1 B-1 AA-2 B-2 AA-3 B-3 [B]テーブルに [CODE3](KEY) [NAME-B] のフィールドがあります。 B-1 NAME-B-1 B-2 NAME-B-2 [C1]テーブルに [NO](KEY) [LINE](KEY) [CODE] [CODEB]のフィールドがあります。 X 1 A-1 AA-2 X 2 A-3 AA-1 Y 1 A-2 AA-3 [C2]テーブルに [NO](KEY) [LINE](KEY) [LINE2](KEY) [BIKO] のフィールドがあります。 X 1 1 BIKO-1 X 1 2 BIKO-2 結果が [NO/LINE/CODE/CODEB/NM1/NM2/BIKO] X 1 A-1 AA-2 NAME-B-1 NAME-B-2 BIKO-1 X 2 A-3 AA-1 (null) NAME-B-1 (null) と、なる様にしたいのです。 要するに、のBIKOは、[C2.LINE2]の一番最小の物を取得したいのです。 SELECT C1.NO, C1.LINE, C1.CODE, C1.CODEB, B.NAMEB AS NM1, B_1.NAMEB AS NM2, C2.LINE2, C2.BIKO FROM ((((C1 LEFT JOIN A ON C1.CODE = A.CODE) LEFT JOIN B ON A.CODE2 = B.CODE3) LEFT JOIN A2 ON C1.CODEB = A2.CODEB) LEFT JOIN B B_1 ON A2.CODE2 = B_1.CODE3) LEFT JOIN C2 ON (C1.LINE = C2.LINE) AND (C1.NO = C2.NO) WHERE (((C1.NO)='X')) ORDER BY C1.NO, C1.LINE, C2.LINE2; と、考えたのですが、結果が X 1 A-1 AA-2 NAME-B-1 NAME-B-2 1 BIKO-1 X 1 A-1 AA-2 NAME-B-1 NAME-B-2 2 BIKO-2 X 2 A-3 AA-1 (null) NAME-B-1(null)(null) と、出てしまいます。 どうすれば良いのでしょうか ? 宜しくお願い致します。

  • OraclのSQL文について(No2)

    前回の質問の続きとなります。 Oracl の SQL文について、教えて下さい。 [A]テーブルに [CODE] と [NAME]フィールドがあるとします。 内容は、 A-1 NAME-1 A-2 NAME-2 A-3 NAME-3 と、します。 [B]テーブルに [CODE] と [NOUKI] と [KIN] フィールドがあるとします。 内容は、 A-1 2005/01/01 100 A-1 2005/01/02 200 A-2 2005/01/01 300 A-2 2005/01/10 400 A-2 2005/12/10 500 と、します。 結果が、 A-1 NAME-1 300 A-2 NAME-2 1200 と、なる様にする為には、どういうSQL文を書けば良いのでしょうか ? SELECT A.CODE, A.NAME, B.KIN FROM A, B WHERE A.CODE = B.CODE ORDER BY A.CODE と、すると A-1 NAME-1 100 A-1 NAME-1 200 A-2 NAME-2 300 A-2 NAME-2 400 A-2 NAME-2 500 と、言う結果がでます。(当然ですが) しかし、 SELECT A.CODE, A.NAME, A2.KIN FROM A, A2 WHERE A.CODE = A2.CODE GROUP BY A.CODE,A.NAME ORDER BY A.CODE と、すると[GROUP BYの式ではありません]と、エラーになってしまいます。 (SUM文以前の問題でした) よろしくお願い致します。

専門家に質問してみよう