【初級編⑧】テーブルの正規化の概要とその手順で説明したように、基本的にSQL Serverのテーブルは無駄な重複をなくすような構造になっています。
商品名や部署名などは別テーブルとして外出しを行い、売上明細等のトランザクションテーブルには商品コードや部署コードしか持たせないようにするのが基本とお伝えしました。
ただ、画面や帳票に売上明細を表示する際には、当然商品名や部署名を表示しなければなりません。その為には売上明細テーブルと商品マスタを「結合」する必要があります。今回はその「テーブル結合」について解説します。
目次
テーブル結合とは
テーブル結合とは「2つ以上のテーブルを何らかのキーを基に結合し、一つのテーブルにすること」です。Excelを例にするととても分かりやすいと思います。
以下画像のような、社員マスタと部署マスタがあるとします。
社員マスタには「部署コード」を保有しており、部署名は部署マスタに格納されているので、社員毎の部署名を表示したい場合は部署マスタから引っ張ってくる必要があります。Excelの場合「VLOOKUP」を使えば簡単に実現できますね。
Excelの解説になってしまうのですが、これは「セルH3の値をキーに、K3からK9を上から順番に検索し、同じ値が見つかった行の2番目のセルの値をI3にセットする」という関数になります。
実際にはこの関数を、社員マスタの一行目の「部署名」のセルに入れ、それを六行目までフィルすることで、6回繰り替えしていることになります。このVLOOKUPの考え方が分かれば、SQL Serverのテーブル結合も理解が早いです。
SQL Serverのテーブル結合動作
SQL Serverでテーブル結合をすると、その名の通りテーブルが結合されますので、2つのテーブルに存在する列全てがくっつきます。社員マスタが7列存在し、部署マスタが2列存在しますので、結合した結果は、9列のテーブルができあがることになります。
内部結合 ~ INNER JOIN ~
内部結合(INNER JOIN)とは、結合する両方のテーブルどちらにも同じキーが存在するレコードのみ残し、それ以外は切り捨てる結合の仕方です。
先ほどの社員マスタに2件レコードを追加しました。
INSERT INTO Table_Syain VALUES('00007', '七道 剛', 28, '男', '1985-02-04' , 270000, '') INSERT INTO Table_Syain VALUES('00008', '増田 八助', 30, '男', '1982-10-05' , 300000, 'B001') ----------------------------------------------------------------------------------------------------------- (1 行処理されました) (1 行処理されました)
社員番号00007の人は、部署コードが空になっており、00008の人は、部署マスタに存在しない部署コードが入力されています。この場合、Excelでさっきと同じVLOOKUPを実行すると部署名はエラー(ヒットしない)となります。
内部結合は、結合するテーブル両方ともにキーが存在するレコードのみ残して他は切り捨てますので、このエラーとなる社員番号00007と00008のレコードは消えます。
INNER JOINの書き方
INNER JOINの書き方を以下に示します。通常のSELECT文と比べて、FROM句の書き方が変わっています。
SELECT * FROM メインテーブルA INNER JOIN 結合テーブルB ON メインテーブルA.キー = 結合テーブルB.キー
通常のSELECT文と同様に、FROM句の後ろにテーブル名を書いた後、続けて「INNER JOIN」と書き、その後ろにまたテーブル名を書くことで、結合するテーブルを指定しています。そして、「ON」に続けて、その2つのテーブルを結合するキーを「メインテーブルのキー と 結合テーブルのキー が同じもの」と指定しています。
社員マスタの部署コードと、部署マスタの部署コードが同じレコード同士を結合されているのが分かります。なお、社員番号00007と00008は、部署マスタには存在しないので結果には表示されていないことが分かります。
メインテーブルとは
上のSQLの中で、「メインテーブル」と「結合テーブル」と書いていますが、テーブル結合の際、どちらのテーブルをメイン(主)と捉えるかということです。「メインテーブル」と「結合テーブル」はただ呼び方が違うだけではなく、このメインテーブルの指定によって結果が変わってきますので注意しましょう。
INNER JOIN(内部結合)では、先に書いた方(左側)がメインテーブルになります。ただし、メインテーブルと結合テーブルとを入れ替えても、両方のテーブルに存在するレコードだけ取得しますので、結果は変わりません。
外部結合 ~ OUTER JOIN ~
外部結合とは、2つのテーブルを結合するのは内部結合と同じですが、どちらか片方のテーブルにデータがあればレコードが取得されます。外部結合には、①LEFT OUTER JOIN(左外部結合)と②RIGHT OUTER JOIN(右外部結合)と③FULL OUTER JOIN(完全外部結合)と3種類存在します。
FULL OUTER JOINは少し難しいので、今回はLEFT OUTER JOINとRIGHT OUTER JOINだけを説明します。
左外部結合 ~ LEFT OUTER JOIN ~
LEFT OUTER JOIN(左外部結合)とは、FROM句に結合するテーブルを書く時、左側に書いた方をメインテーブルにする外部結合になります。その結果、左側のメインテーブルに存在するレコードは、仮に右側のテーブルに同じキーのレコードが無くても全て取得されますが、反対に右側のテーブルだけにしか存在しないレコードは取得されません。
LEFT OUTER JOINの書き方
LEFT OUTER JOINの書き方は、基本的にはINNER JOINの時と同じで、「INNER」が「LEFT OUTER」に置き換わるだけです。
SELECT * FROM メインテーブルA LEFT OUTER JOIN 結合テーブルB ON メインテーブルA.キー = 結合テーブルB.キー
社員番号00007と00008のレコードの部署コードは部署マスタに存在しないが、今回は社員マスタがメインテーブルなので、そのまま残ります。さらに、当該2レコードの部署マスタの部分は値が存在しないので、NULLになります。
右外部結合 ~ RIGHT OUTER JOIN ~
RIGHT OUTER JOIN(右外部結合)は、LEFT OUTER JOINと比べて、JOINの右側に書いたテーブルがメインテーブルになるだけの違いしかありません。
RIGHT OUTER JOINの書き方
RIGHT OUTER JOINは、LEFT OUTER JOINの「LEFT」が「RIGHT」に変わり、メインテーブルをJOINの右側に書きます。
SELECT * FROM 結合テーブルB RIGHT OUTER JOIN メインテーブルA ON 結合テーブルB.キー = メインテーブルA.キー
LEFT OUTER JOINとRIGHT OUTER JOINは、JOINの左に書いたテーブルをメインテーブルにするか、右に書いたテーブルをメインテーブルにするかどうかの違いしかありません。つまり、次の2つのSQLは同じ結果になります。
SELECT * FROM メインテーブルA LEFT OUTER JOIN 結合テーブルB ON メインテーブルA.キー = 結合テーブルB.キーSELECT * FROM 結合テーブルB RIGHT OUTER JOIN メインテーブルA ON 結合テーブルB.キー = メインテーブルA.キーですので、基本的に外部結合をする際はLEFT OUTER JOINならLEFT OUTER JOINに統一、RIGHT OUTER JOINならRIGHT OUTER JOINに統一した方がいいです。ちなみに私はLEFT派です。文字は左から読みますからその方が分かりやすいです。
テーブル結合の基礎はこれで終了です。