
結合とは?
正規化されて、分割されたテーブル同士に対して、結合条件が満たされた行を1行ずつつないで一つの非正規形の表にすること。
結合の動作の仕組み
結合元のテーブルの値を結合条件にして、1行ずつ結合先のテーブルの行で結合条件に合うものがないか探していく仕組みになっています。
しかし、動作の仕組み的に、下記のように様々なケースが考えられるでしょう。
ケース1:重複があった場合の結合は?
結合先のテーブルの、結合条件の値に重複があった場合は、結合元のテーブルの行を結合先の重複件数に合うように複製されてしまいます。
なので、結合結果が、元のテーブルの行数より増えてしまいます。
対策
対策としては、テーブルの設計段階(論理設計時に考える。)で、「多:多」の関係を作らないことです。
テーブル設計の基本的な流れについては、下記の記事で解説していますので、ご覧下さい。
ケース2:結合条件に合致する項目がない場合は?
逆に、結合先に結合条件に合致する項目がなかった場合は、結合結果が、元のテーブルの行数よりも減ってしまいます。
対策
結合結果として、相手先が見つからなかった場合に、行数が減ってしまうのは問題があります。
対策1:外部結合を使う
対策として「外部結合」を使うパターンがあります。
「外部結合」であれば、相手先が見つからなかったとしても、NULLとして結果を返してくれるので、行数が減ることがありません。
対策2:外部キーを使う
「外部キー」を使えば、DBMSがシステム的に、親テーブルに存在しない値が入力されるのを防いでくれます。
ただ、外部キーにも、メリット、デメリットありますので、下記の記事を参考にされて下さい。
通常の内部結合
下記の構文を使います。
1 2 3 4 |
SELECT 選択列 FROM テーブルA JOIN テーブルB ON 結合条件 |
JOINを使わない内部結合
RDBMSによっては、下記のようにJOIN句を使わずに、内部結合を記述することができます。
1 2 3 |
SELECT 選択列 FROM テーブルA,テーブルB WHERE 結合条件 |
標準SQLでも定義されていて、特に年配プログラマが書かれたSQL文では未だにこうした記述をされているケースは少なくありません。
しかし、この記述方法は、以下理由によりあまり推奨されないです。
- 結合元のテーブルがわかりずらい。
- WHERE句に、結合条件だけでなく、絞込み条件も記述するため、どれが結合条件で、どれが絞り込み条件なのか判別がしずらい。
- 構文自体が古い構文と認定されつつあるので、いずれこの構文が使われなくなりえます。
特に古くから作られたシステムではそうですが、現場でも良く見かける内部結合の記述方法なので、新規では書かなくてよいですが、最低限知識として持っておき読めるようにしておきましょう。
なお、WHERE句を使わなかった場合は、「クロス結合(CROSS JOIN)」をした結果と同じになります。内部結合をしたい場合は、必ずWHERE句で結合条件を指定する必要があります。
外部結合
左外部結合
構文
1 2 3 4 |
SELECT 選択列 FROM テーブルA(左表) LEFT JOIN テーブルB(右表) ON 結合条件 |
特徴
左表のデータを必ず残す。
右外部結合
構文
1 2 3 4 |
SELECT 選択列 FROM テーブルA(左表) RIGHT JOIN テーブルB(右表) ON 結合条件 |
特徴
右表のデータを必ず残す。
「左外部結合(LEFT JOIN)」と「右外部結合(RIGHT JOIN)」をどのように使い分けるか?
基本的には、どちらの結合も機能的な差はありません。
一般的には、先にマスタとなるテーブルが出てくる「LEFT JOIN」を使うケースが多いようですが、LEFT JOINを使わなければならないという明確な理由はありません。
完全外部結合
構文
1 2 3 4 |
SELECT 選択列 FROM テーブルA(左表) FULL JOIN テーブルB(右表) ON 結合条件 |
特徴
両方の表データを必ず残す。
外部結合の例
テストデータ
USER_MASTER
USER_ID | DEPT_NO | USER_NAME |
---|---|---|
21 | 1002 | 小泉 純子 |
22 | 1003 | 小泉 三郎 |
23 | 1004 | 小泉 花子 |
20 | 1001 | 小泉 純一 |
AUTHORIZATION
USER_ID | LOGIN_ID | PASSWD |
---|---|---|
21 | 10002 | 234567 |
20 | 10001 | 1234567 |
左外部結合
LEFT JOINを使う場合
1 2 3 |
SELECT * FROM USER_MASTER u LEFT JOIN AUTHORIZATION a ON u.USER_ID = a.USER_ID |
少し古い書き方
条件に「(+)」を付けた方のテーブルを基準にデータを残します。
1 2 |
select * from user_master u,authorization a where u.USER_ID = a.USER_ID(+) |
実行結果
USER_ID | DEPT_NO | USER_NAME | USER_ID | LOGIN_ID | PASSWD |
21 | 1002 | 小泉 純子 | 21 | 10002 | 234567 |
20 | 1001 | 小泉 純一 | 20 | 10001 | 1234567 |
23 | 1004 | 小泉 花子 | NULL | NULL | NULL |
22 | 1003 | 小泉 三郎 | NULL | NULL | NULL |
LEFT JOIN決め打ちルールについて
LEFT JOINにON句を使って抽出をすればINNER JOINと同じように使うこともできます。なので、開発現場によっては「LEFT JOINのみを使うこと」とルールを決めている現場もあるようです。
ただ、これは以下の理由によりあまり良くありません。
NULLが入る
なぜならLEFT JOINはカラムにNULLが入る可能性があるためです。カラムにNULLが入ると必然的に思わぬバグが発生する可能性が上がります。
無意味なWHERE句操作が入る場合がある。
そもそも、INNER JOINを使っていればLEFT JOINしてからのちに条件を抽出するという操作は不要になる場合が多いです。無意味な操作をしいられることになりパフォーマンスに影響が出てしまいます。
クロス結合(CROSS JOIN)
この結合は、結論から申しますと、実務で扱うことはほぼないです。
集合で言えば、「直積」になるので、大量の行数が出てきます。
パフォーマンスを意識した結合
少し、SQL上級者向けになりますが、結合処理は非常に負荷がかかる処理です。
パフォーマンスを意識した結合についても考慮できるようにしましょう。詳しくは、下記の記事で解説しています。
この記事へのコメントはありません。