複数テーブルの検索

この章のコードはSample_SQL8.txtを使用します。

SQL例に使用するテーブル

複数のテーブルを検索するためには対象となるテーブル同士を結合する必要があります。
この章ではテーブル「Staff」(担当者マスター)、「Employee」(従業員マスター)および「Position」(役職マスター)の3つを使用してSQL例を考えてみましょう。
テーブル「Staff」と「Employee」はプライマリーキーの「ID」を共有しています。つまり、IDの値が同じレコードはテーブル「Staff」でも「Employee」でも同一人物の属性をデータとして持っています。要はテーブル「Employee」は「Staff」の詳細情報であるといえます。また、テーブル「Position」は「Employee」の各従業員に設定した役職IDの役職名と役職手当を定義しています。
(注)上記3テーブルはSQL講座用教材としての都合上、リレーションシップを設定していません。

下図は上記3テーブルの全リストです。以降、例に挙げる各SQLの結果は下図を参照して、元のデータの構成がどうであったかをベースに検証して下さい。

Staff(担当者マスター)】

Employee(従業員マスター)】

Position(役職マスター)】

内部結合(WHERE句使用)

テーブル結合とは、2つ以上のテーブルを何らかのキー(結合条件)を基に結合して検索する手法のことです。
内部結合とはテーブル同士で結合条件に合致した行のみ選択結果に含める結合方法です。キーとなる列の値がどちらかのテーブルにしか存在しない行は選択結果として取り出すことができません。

WHERE句を使用した内部結合の書式は下記のとおりです。
なお、書式の最初に記述するテーブルを「親テーブル」、2つ目以降に記述するテーブルを「子テーブル」と呼びます。
<
書式8.1>
SELECT <
列名1>,<列名2>,…
     FROM <
親テーブル名>,<子テーブル名>
     WHERE <
親テーブル名>.<列名3> = <子テーブル名>.<列名4>;

(注)WHERE句で指定した条件が結合条件になります。

<SQL8.1>
SELECT
     Staff.ID,
     Name,
     ZipCode,
     Adress1,
     Adress2
     FROM Staff,Employee
     WHERE Staff.ID= Employee.ID;

 この例では親テーブルは「Staff」、子テーブルは「Employee」です。

<SQL8.1>の実行結果】

ID」列に注目すると、「Staff」にあって「Employee」に登録されていない3911以降、また、「Employee」にあって「Staff」に登録されていない23が検索結果に表示されていないことが確認されます。

なお、クエリーを作成した際に自動生成されるSQLコードはWHERE句を使用した書式です。詳しくは「Base中級」コース第8章、「単位名付き品目マスター用クエリーの作成」の節で掲載したSQL文を参照して下さい。

内部結合(JOIN句使用)

JOIN句を使用した内部結合の書式は下記のとおりです。書式の記述の中に「[]」(ブラケット)がありますが、これは前述したように書式記述上の約束事の一つです。「[]」で囲まれたキーワード「INNER」は省略可能で、省略した場合は「INNER」を指定した時と同じ結果になります。
<書式8.2>
SELECT <
列名1>,<列名2>,…
FROM <
親テーブル名> [INNER] JOIN <子テーブル名>
     ON <
親テーブル名>.<列名3> = <子テーブル名>.<列名4>;

(注)JOIN句に続けて記述するON句で指定した条件が結合条件になります。

<SQL8.2>
SELECT
     Staff.ID,
     Name,
     ZipCode,
     Adress1,
     Adress2
     FROM StaffINNER JOIN Employee
          ON Staff.ID= Employee.ID;

<SQL8.2>の実行結果】

<SQL8.1>と同じ実行結果になることが確認されます。

左外部結合(JOIN句使用)

外部結合は内部結合とは違って、条件に指定した列の値が片側のテーブルにしか存在しない場合も検索結果に含める方法です。外部結合には左外部結合と右外部結合があり、記述するテーブルの順序によって決められた親テーブルが優先する場合に左外部結合(LEFT OUTER JOIN)、子テーブルが優先する場合に右外部結合(RIGHT OUTER JOIN)となります。優先されたテーブルは結合条件が満たない場合であってもすべて検索結果に出力されます。

JOIN句を使用した左外部結合の書式は下記のとおりです。
<
書式8.3>
SELECT <
列名1>,<列名2>,…
     FROM <
親テーブル名> LEFT [OUTER] JOIN <子テーブル名>
          ON <
親テーブル名>.<列名3> = <子テーブル名>.<列名4>;

<SQL8.3>
SELECT
     Staff.ID,
     Name,
     ZipCode,
     Adress1,
     Adress2
     FROM StaffLEFT OUTER JOIN Employee
          ON Staff.ID= Employee.ID;

 この例では親テーブル「Staff」のデータが優先して出力されます。

<SQL8.3>の実行結果】(一部)

親テーブル「Staff」にあって子テーブル「Emproyee」に登録されていないID=3,9,11等のレコードも出力されていることが確認されます。

右外部結合(JOIN句使用)

JOIN句を使用した右外部結合の書式は下記のとおりです。
<
書式8.4>
SELECT <
列名1>,<列名2>,…
     FROM <
親テーブル名> RIGHT [OUTER] JOIN <子テーブル名>
          ON <
親テーブル名>.<列名3> = <子テーブル名>.<列名4>;

<SQL8.4>
SELECT
     Staff.ID,
     Name,
     ZipCode,
     Adress1,
     Adress2
     FROM StaffRIGHT OUTER JOIN Employee
          ON Staff.ID= Employee.ID;

 この例では子テーブル「Employee」のデータが優先して出力されます。

<SQL8.4>の実行結果】

子テーブル「Emproyee」にあって親テーブル「Staff」に登録されていないID=23のレコードも最下行に出力されていることが確認されます。

3つのテーブル結合(WHERE句使用)

WHERE句を使用した3つのテーブル結合の書式は下記のとおりです。子テーブル名を複数指定し、2つめの結合条件をキーワード「AND」の次に記述します。
<
書式8.5>
SELECT <
列名1>,<列名2>,…
     FROM <
親テーブル名>,<子テーブル名1>,<子テーブル名2>
     WHERE <
親テーブル名>.<列名3> = <子テーブル名1>.<列名4>
           AND <
親テーブル名または子テーブル名1>.<列名5> = <子テーブル名2>.<列名6>;

<SQL8.5>
SELECT
     Staff.ID,
     Staff.Name,
     BirthDay,
     Position_ID,
     Position.Name AS
役職名,
     Salary,
     Allowance
     FROM Staff,Employee,Position
     WHERE Staff.ID= Employee.ID
           AND Employee.Position_ID= Position.ID;

 この例では親テーブルは「Staff」、子テーブルは「Employee」と「Position」です。

<SQL8.5>の実行結果】

3つのテーブル結合(JOIN句使用)

JOIN句を使用する場合は、FROM句で親テーブル名を指定します。次に最初のJOIN句では子テーブル(いわば長男)を指定し、ON句で親と長男の結合条件を記述します。次のJOIN句では子テーブル(いわば次男)を指定し、ON句で親と次男の結合条件を記述します。
<
書式8.6>
SELECT <
列名1>,<列名2>,…
     FROM <
親テーブル名>
{ [INNER] | LEFT [OUTER] | RIGHT [OUTER] } JOIN <
子テーブル名1>
          ON <
親テーブル名>.<列名3> = <子テーブル名1>.<列名4>
{ [INNER] | LEFT [OUTER] | RIGHT [OUTER] } JOIN <
子テーブル名2>
          ON <
親テーブル名>.<列名5> = <子テーブル名2>.<列名6>;

(注)
上記の書式
JOIN句のオプションを正式に表現したため一見難解そうに見えますが、これまでに何度かご紹介した書式記述上の約束事を理解すれば、それほど難しくありません。
オプションの対象となる個所を「{}」(ブレースカール)で囲っており、要は「JOIN句は下記の3つ記述のいずれかを選択することが可能です」という意味になります。
INNER JOIN
(ただし「INNER」は省略可能)
LEFT OUTER JOIN
(ただし「OUTER」は省略可能)
RIGHT OUTER JOIN
(ただし「OUTER」は省略可能)

<SQL8.6>
SELECT
     Staff.ID,
     Staff.Name,
     BirthDay,
     Position_ID,
     Position.Name AS
役職名,
     Salary,
     Allowance
     FROM Employee,
     INNER JOIN Staff
           ON Employee.ID= Staff.ID
     INNER JOIN Position
           ON Employee.Position_ID= Position.ID;

 この例では親テーブルは「Employee」、子テーブルは「Staff」(長男)と「Position」(次男)です。

<SQL8.6>の実行結果】

自己結合(WHERE句使用)

自己結合についてはテーブル「Department」(部門マスター)を例に説明します。下図がテーブル「Department」の全レコードです。ID=G110の列「Parent_ID」(上位組織ID)の値をみると、「G100」となっています。つまり総務課は総務部の下部組織である事を意味しています。この部門名を取得する場合、同じテーブルのID=G100の列「Name」の値「総務部」を検索する必要があります。

このような場合は別名(エイリアス)を使い、一つのテーブルを、あたかも別の2つのテーブルであるかのように扱って処理します。書式は下記のとおりです。
<
書式8.7>
SELECT <
列名1>,<列名2>,…
     FROM <
テーブル名> AS <別名1>,<テーブル名> AS <別名2>
     WHERE <
1>.<列名3> = <別名2>.<列名4>;

<SQL8.7>
SELECT
     a.ID,
     a.Name,
     a.Parent_ID,
     b.Name AS
上位部門名
     FROM DepartmentAS a,DepartmentAS b
     WHERE a.Parent_ID= b.ID;

 この例では親テーブルは別名「a」、子テーブルは別名「b」となります。

<SQL8.7>の実行結果】

列「上位部門名」が正常に部門名称になっているのが確認されます。なお、内部結合のためID=G100ID=S100のレコードは上位組織が定義されていないので検索されていません。これを解決するためには下記の例のようにJOIN句を使って左外部結合します。
<SQL
8.8>
SELECT
     a.ID,
     a.Name,
     a.Parent_ID,
     b.Name AS
上位部門名
     FROM DepartmentAS a
     LEFT JOIN DepartmentAS b
         ON a.Parent_ID= b.ID;

<SQL8.8>の実行結果】

この例は自己結合を説明するためには分かりやすいのですが、実務的ではありません。実務的な例として下記の例を紹介しておきます。
<SQL
8.9>
SELECT
     a.ID,
     a.Name,
     Employee.BirthDay,
     Position_ID,
     Position.Name,
     Salary,
     Allowance,
     Superior_ID,
     b.Name AS
上司名
     FROM Employee
     INNER JOIN StaffAS a
           ON Employee.ID= a.ID
     INNER JOIN Position
           ON Employee.Position_ID= Position.ID
     LEFT JOIN StaffAS b
           ON Employee.Superior_ID= b.ID;

<SQL8.9>の実行結果】

テーブル「Staff」が子テーブルとして2度使われ、本人の氏名と上司の氏名が表示されているのが確認されます。

Back> 7.検索結果の並べ替え(ソート)
Next> 9.集約時のグループ化

タイトルとURLをコピーしました