zukucode
主にWEB関連の情報を技術メモとして発信しています。

SQL FROM句で複数のテーブルを結合するポイント

FROM句では取得したいテーブルのテーブル名を指定します。

以下のようなテーブルがあるとします。

departmentは社員が所属する部署の情報を格納しています。

また、employeedepartmentの関係は1対1とします。

employee(社員)
idfirst_namelast_namedepartment_id
1一郎山田1
2次郎佐藤2
3三郎田中1
department(部署)
iddepartment_name
1営業部
2人事部

このとき、社員の一覧と所属部署のデータを取得したい場合、FROM句で以下のように指定します。

SELECT
  employee.first_name,
  employee.last_name,
  department.department_name
FROM
  employee
  JOIN department
    ON employee.department_id = department.id

-- テーブルに別名を指定する場合
SELECT
  T1.first_name,
  T1.last_name,
  T2.department_name
FROM
  employee AS T1
  JOIN department AS T2
    ON T1.department_id = T2.id
取得結果
first_namelast_namedepartment_name
一郎山田営業部
次郎佐藤人事部
三郎田中営業部

テーブルの結合

複数のテーブルを結合する場合はまず結合したいテーブルをJOINのあとに指定します。そしてONのあとに結合条件を指定します。

結合条件とは

結合条件を指定せずにテーブルを2つ指定すると、指定した2つのテーブルの直積の結果が出力されてしまいます。

上記の例だとemployeeにはデータが3件、departmentにはデータが2件あるので3×2で6通りの組み合わせが考えられます。

なので以下のように6件が出力されます。(わかりやすくするためdepartment_idも出力しています)

first_namelast_namedepartment_id(employee)id(department)department_name
一郎山田11営業部
一郎山田12人事部
次郎佐藤21営業部
次郎佐藤22人事部
三郎田中11営業部
三郎田中12人事部

このうち、取得したいデータはdepartment_id(employee)id(department)が同じデータになります。

逆にdepartment_id(employee)id(department)が異なるデータはテーブル間の関連性のない意味のないデータになるので取得する必要がありません。

よって、結合条件でemployee.department_id = department.idと指定します。

結合のポイント

上記の例では結合するテーブル同士が1対1で、なおかつ結合先のデータが必ず存在していることが前提となっています。

そのため、混乱することはないかと思いますが、SQLが複雑になってくると、結合の理解があいまいだと予期せぬ結果になってしまうことがあります。

最初にメインとなるテーブルを決め、結合するテーブルが何対何になるのかと、結合先のデータが必ず存在しているかどうか(idで結合する場合はそのidが結合先のテーブルに必ず存在しているかどうか)を必ず意識して結合していくと混乱せずにスムーズに実装できるかと思います。

例えば上記の例では社員単位(1社員1行)での出力になるはずですが、結合条件を正しく指定していないと、同一社員が2行出力されています。

そのような結果は仕様通りではないので結合条件を見なおす必要があります。


関連記事

  • Oracle 文字列の中で指定した文字を削除する

    Oracleで文字列の中で指定した文字を削除する方法を紹介します。REPLACEを使用して削除したい文字をNULL(空文字)に置き換えることで削除します。Oracleは空文字をNULLとして扱うので、...


  • SQL GROUP BYで複数の行を集計して1行で取得する

    GROUP BY 列名で集約したい列を指定します。上記例の場合は部署ごとに集約したいのでdepartment_idを指定しています。GROUP BYで指定した列以外の列をSELECT句で取得したい場合...


  • SQL FROM句で複数のテーブルを結合するポイント

    FROM句では取得したいテーブルのテーブル名を指定します。複数のテーブルを結合する場合はまず結合したいテーブルをJOINのあとに指定します。そしてONのあとに結合条件を指定します。結合条件を指定せずに...


  • SQL DISTINCTで重複行を1行のみ表示する方法

    SELECTのあとにDISTINCTをつけると、同一のレコードを1行のみ取得するようになります。上記例ではid=1と4のレコードの取得結果は同じになるので、本来は2行出力されるはずのレコードが、DIS...


  • PostgreSQL 現在のシステム日付・時刻を取得する

    OracleのSYSDATEのように、PostgreSQLで現在のシステム日付や時刻を取得する方法を紹介します。YYYY/MM/DDやYYYY-MM-DDのように、date型を取得するにはCURREN...


  • SQL FROM句での副問合わせの基本的な考え方と注意点

    FROM句で副問合わせを行うと、SELECTした結果を1つのテーブルとして、他のテーブルと結合できます。SELECTした結果をVIEWとして予め定義しておくことができますが、FROM句で副問合わせでは...


  • PostgreSQL 日付の加算・減算を行う

    PostgreSQLで日付の加算・減算を行う方法を紹介します。日付型のカラムに対しては、数字の計算と同じ要領で行うことができます。YYYYMMDD形式などの文字列型のカラムの場合は、日付型に変換してか...


  • PostgreSQL ISNULLやNVLのようにNULLを判定する方法

    PostgreSQLでSQL ServerのISNULLやOracleのNVLのように、NULLの場合に別の値を取得するにはCOALESCEを使用します。使い方はISNULLやNVLと同じように、第一...


  • PL/SQL 変数を宣言して値を設定する

    PL/SQLで変数を宣言して値を設定する方法を紹介します。ASとBEGINの間で変数を宣言します。宣言と同時に値をセット(初期化)も可能です。変数への代入は=ではなく:=で行います。


  • PL/SQL TRUNCATE TABLEをストアドプロシージャに定義する

    PL/SQLでTRUNCATE処理をストアドプロシージャに定義する方法を紹介します。そのまま定義すると「記号TABLEが見つかりました。」のコンパイルエラーになってしまうので、動的SQLで定義します。