【DB】テーブル結合したデータ参照【SQL】

テーブルを正規化すると単純に1テーブルだけの参照ではデータ取得ができません。そのため、複数のテーブルを結合して参照する必要があります。

テーブル結合

テーブルを結合する場合「SELECT句」に「JOIN」という条件を追加して複数のテーブルを結合します。

今回結合するテーブルは以下の通りです。

※テーブル作成までの経緯については下記を参照ください。

テーブルの正規化

テーブル構造

テーブル名:WARSHIP

No. カラム名 データ型 主キー
1 ID NUMERIC(5)
2 NAME VARCHAR(100)
3 WARSHIP_TYPE_ID NUMERIC(2)
4 LAUNCH_DATE DATE

テーブル名:WARSHIP_TYPE

No. カラム名 データ型 主キー
1 ID NUMERIC(2)
2 NAME VARCHAR(50)

テーブルデータ

テーブル名:WARSHIP_TYPE

ID NAME
1 戦艦
2 空母
3 駆逐艦
4 海防艦

テーブル名:WARSHIP

ID NAME WARSHIP_TYPE_ID LUNCH_DATE
1 大和 1 1940年8月8日
2 赤城 2 1925年4月22日
3 五月雨 3 1935年7月6日
4 朝霜 3 1943年7月18日

エイリアス(別名)

テーブル結合を実施する場合、SQL文を少しでも簡素化する方法として「エイリアス」を定義します。

WARSHIP:「A」
WARSHIP_TYPE:「B」

単純にアルファベットを並べてエイリアスを定義しました。

※エイリアスにテーブル名の一部を省略した名称などを使うこともあります。個人的には略称を扱わないようにしております。略称はかぶってしまう場合が多々あるためルール化が複雑になるためです。

結合するSQL文

「SELECT」~「FROM」~「JOIN」~「ON」(~)

  • SELECT:取得したい項目を指定します。
  • FROM:取得したい項目を管理するテーブルを指定します。
  • JOIN:結合して取得した項目を管理するテーブルを指定します。
  • ON:結合する条件を指定します。
  • WHERE:取得するデータを絞り込む条件を指定します。

実際に結合してみます。

SELECT
  A.ID,
  A.NAME,
  B.NAME AS TYPE_NAME,
  A.LAUNCH_DATE
FROM WARSHIP A
JOIN WARSHIP_TYPE B ON (A.WARSHIP_TYPE_ID = B.ID)

結合したすべてのデータが出力されます。

※SQL文に「AS~」と指定しています。これはカラム名に対してのエイリアスになります。

ID NAME TYPE_NAME LAUNCH_DATE
1 大和 戦艦 1940年8月8日
2 赤城 空母 1925年4月22日
3 五月雨 駆逐艦 1935年7月6日
4 朝霜 駆逐艦 1943年7月18日

このようにカラム名とエイリアス指定した名称でデータが取得されます。この結合方法は内部結合といいます。

内部結合・外部結合について

上記で結合してデータを参照する方法を内部結合といいます。内部結合に対して外部結合という結合方法がありあます。

内部結合とは

結合するお互いのテーブルに存在する情報を出力する場合を「内部結合」するといいます。

上記例では「WARSHIP_TYPE」テーブルに「4:海防艦」が定義されているのに出力結果には存在しておりません。これは内部結合を行った結果になります。

内部結合はSQL文で明示的に記載することもできます。上記SQL文は内部結合の省略形式になります。

SELECT
  A.ID,
  A.NAME,
  B.NAME AS TYPE_NAME,
  A.LAUNCH_DATE
FROM WARSHIP A
INNER JOIN WARSHIP_TYPE B ON (A.WARSHIP_TYPE_ID = B.ID)

「JOIN」を「INNER JOIN」に変更しました。この「INNER JOIN」句が内部結合の明示的な指定方法です。

外部結合とは

外部結合は、片側のテーブルにある情報すべてと結合できた情報を表示します。内部結合では抽出できなかった「WARSHIP_TYPE」テーブルの「4:海防艦」も出力したい場合は以下のようなSQL文なります。

SELECT
  A.ID,
  A.NAME,
  B.NAME AS TYPE_NAME,
  A.LAUNCH_DATE
FROM WARSHIP A
RIGHT JOIN WARSHIP_TYPE B ON (A.WARSHIP_TYPE_ID = B.ID)

「INNER JOIN」を「RIGHT JOIN」に変更しました。「RIGHT JOIN」を指定したことで「WARSHIP_TYPE」テーブルのすべてを取得するという指定になります。

ID NAME TYPE_NAME LAUNCH_DATE
1 大和 戦艦 1940年8月8日
2 赤城 空母 1925年4月22日
3 五月雨 駆逐艦 1935年7月6日
4 朝霜 駆逐艦 1943年7月18日
NULL NULL 海防艦 NULL

取得できないデータはすべて「NULL」として取得されます。

また、「RIGHT」という表現がでてくると「LEFT」はできないのかなと考えます。「LEFT JOIN」も可能です。上記SQL文で「LEFT JOIN」を指定すると「WARSHIP」テーブルのすべてを取得という指定になります。指定する意味は違いますが内部結合の時と同じ内容が取得されます。

 

SELECT
  A.ID,
  A.NAME,
  B.NAME AS TYPE_NAME,
  A.LAUNCH_DATE
FROM WARSHIP A
LEFT JOIN WARSHIP_TYPE B ON (A.WARSHIP_TYPE_ID = B.ID)
ID NAME TYPE_NAME LAUNCH_DATE
1 大和 戦艦 1940年8月8日
2 赤城 空母 1925年4月22日
3 五月雨 駆逐艦 1935年7月6日
4 朝霜 駆逐艦 1943年7月18日

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です