INNER JOIN

テーブルの結合は、SELECT文のFROM句の後に複数テーブルを指定し、WHEREで条件を指定することで可能だが、
今回はJOINという演算子を使用して結合を行う。
JOINにはいくつかの種類があり、目的に応じて使い分ける必要がある。
またJOINは演算子なので、基本的に2つのテーブルの結合になる。3つ以上のテーブルの結合は後述

準備

以前定義した、grade, class, studentテーブルを利用し、次のようなテーブルを作成する。

g01
gnumcolor
1
2
3
g02
gnumcnumcolor
1100
2100
3100
g03
numcolor
1
2
3
c01
gnumcnumcharge
11田中
12鈴木
13佐藤
14松井
21岡田
c02
gnumcnumsnumcharge
11200田中
12200鈴木
13200佐藤
14200松井
21200岡田
c03
gnumnumcharge
11田中
12鈴木
13佐藤
14松井
21岡田
s01
gnumcnumsnumname  …  
111大石友美
112中村優作
113北川陽子
114望月慎太郎
115木村葉子
116藤田智子
121石川大地
  1. 次のSQLをファイルとして作成。(setup121.sql)

    
    
  2. ログイン画面から実行。

    oddtbs=> \i setup121.sql
    DROP TABLE
    ...
    SELECT
    ...
    oddtbs=> select * from g01;
    oddtbs=> select * from g01;
     gnum | color
    ------+-------
        1 | 青
        2 | 赤
        3 | 緑
    (3 rows)
    oddtbs=> select * from g02;
     gnum | cnum | color
    ------+------+-------
        1 |  100 | 青
        2 |  100 | 赤
        3 |  100 | 緑
    (3 rows)
    oddtbs=> select * from g03;
     num | color
    -----+-------
       1 | 青
       2 | 赤
       3 | 緑
    (3 rows)
    oddtbs=> select * from c01;
     gnum | cnum | charge
    ------+------+--------
        1 |    1 | 田中
        1 |    2 | 佐藤
        1 |    3 | 鈴木
        1 |    4 | 松井
        2 |    1 | 岡田
        2 |    2 | 山本
        2 |    3 | 斎藤
        2 |    4 | 吉田
        3 |    1 | 村山
        3 |    2 | 森田
        3 |    3 | 原田
        3 |    4 | 島田
    (12 rows)
    oddtbs=> select * from c02;
     gnum | cnum | snum | charge
    ------+------+------+--------
        1 |    1 |  200 | 田中
        1 |    2 |  200 | 佐藤
        1 |    3 |  200 | 鈴木
        1 |    4 |  200 | 松井
        2 |    1 |  200 | 岡田
        2 |    2 |  200 | 山本
        2 |    3 |  200 | 斎藤
        2 |    4 |  200 | 吉田
        3 |    1 |  200 | 村山
        3 |    2 |  200 | 森田
        3 |    3 |  200 | 原田
        3 |    4 |  200 | 島田
    (12 rows)
    oddtbs=> select * from c03;
     gnum | num | charge
    ------+-----+--------
        1 |   1 | 田中
        1 |   2 | 佐藤
        1 |   3 | 鈴木
        1 |   4 | 松井
        2 |   1 | 岡田
        2 |   2 | 山本
        2 |   3 | 斎藤
        2 |   4 | 吉田
        3 |   1 | 村山
        3 |   2 | 森田
        3 |   3 | 原田
        3 |   4 | 島田
    (12 rows)
    oddtbs=> select * from s01;
     gnum | cnum | snum |     name
    ------+------+------+--------------
        1 |    1 |    1 | 大石友美
        1 |    1 |    2 | 中村優作
        1 |    1 |    3 | 北川陽子
        1 |    1 |    4 | 望月慎太郎
        1 |    1 |    5 | 木村葉子
        1 |    1 |    6 | 藤田智子
        1 |    2 |    1 | 石川大地
    ...
    ...
        3 |    4 |    4 | 鷲山綾子
        3 |    4 |    5 | 内山絢平
        3 |    4 |    6 | 梶間昇平
    (72 rows)
    

CROSS JOIN

CROSS JOINは全ての行の組み合わせを選択する。これを直積という。
目的が直積であることから、条件を指定することはできない。

SELECT 選択リスト FROM テーブル1 CROSS JOIN テーブル2;
oddtbs=> select * from g01 cross join g02;
 gnum | color | gnum | cnum | color
------+-------+------+------+-------
    1 | 青    |    1 |  100 | 青
    1 | 青    |    2 |  100 | 赤
    1 | 青    |    3 |  100 | 緑
    2 | 赤    |    1 |  100 | 青
    2 | 赤    |    2 |  100 | 赤
    2 | 赤    |    3 |  100 | 緑
    3 | 緑    |    1 |  100 | 青
    3 | 緑    |    2 |  100 | 赤
    3 | 緑    |    3 |  100 | 緑
(9 rows)

NATURAL JOIN

NATURAL JOINは、両テーブルの名前と型が同じである全ての列が等しい組み合わせを選択する。
すなわち、両テーブルの名前と型が同じである全ての列を結合の条件として使用する。
また同じである列は重複して表示しない。
条件が完全に決定されるため、条件の指定はできない。

SELECT 選択リスト FROM テーブル1 NATURAL JOIN テーブル2;
oddtbs=> select * from g01 natural join c01;
 gnum | color | cnum | charge
------+-------+------+--------
    1 | 青    |    1 | 田中
    1 | 青    |    2 | 佐藤
    1 | 青    |    3 | 鈴木
    1 | 青    |    4 | 松井
    2 | 赤    |    1 | 岡田
    2 | 赤    |    2 | 山本
    2 | 赤    |    3 | 斎藤
    2 | 赤    |    4 | 吉田
    3 | 緑    |    1 | 村山
    3 | 緑    |    2 | 森田
    3 | 緑    |    3 | 原田
    3 | 緑    |    4 | 島田
(12 rows)

※ 両テーブルのgnum列が結合の条件として使用された。

oddtbs=> select * from g01 natural join s01;
 gnum | color | cnum | snum |     name
------+-------+------+------+--------------
    1 | 青    |    1 |    1 | 大石友美
    1 | 青    |    1 |    2 | 中村優作
    1 | 青    |    1 |    3 | 北川陽子
    1 | 青    |    1 |    4 | 望月慎太郎
    1 | 青    |    1 |    5 | 木村葉子
    1 | 青    |    1 |    6 | 藤田智子
    1 | 青    |    2 |    1 | 石川大地
...
...
    3 | 緑    |    4 |    4 | 鷲山綾子
    3 | 緑    |    4 |    5 | 内山絢平
    3 | 緑    |    4 |    6 | 梶間昇平
(72 rows)

※ 両テーブルのgnum列が結合の条件として使用された。

oddtbs=> select * from c01 natural join s01;
 gnum | cnum | charge | snum |     name
------+------+--------+------+--------------
    1 |    1 | 田中   |    1 | 大石友美
    1 |    1 | 田中   |    2 | 中村優作
    1 |    1 | 田中   |    3 | 北川陽子
    1 |    1 | 田中   |    4 | 望月慎太郎
    1 |    1 | 田中   |    5 | 木村葉子
    1 |    1 | 田中   |    6 | 藤田智子
...
...
    3 |    4 | 島田   |    4 | 鷲山綾子
    3 |    4 | 島田   |    5 | 内山絢平
    3 |    4 | 島田   |    6 | 梶間昇平
(72 rows)

※ 両テーブルのgnumとcnum列が結合の条件として使用された。

NATURAL JOINが使用できない例

NATURAL JOINは同じ名前と型の列を全て結合の条件として使用する。
よって、同じ名前と型の列の中に結合の条件として使用したくない列が含まれている場合、NATURAL JOINは使用できない。

oddtbs=> select * from g02 natural join c01;
 gnum | cnum | color | charge
------+------+-------+--------
(0 rows)

oddtbs=> select * from g02 natural join s01;
 gnum | cnum | color | snum | name
------+------+-------+------+------
(0 rows)

oddtbs=> select * from c02 natural join s01;
 gnum | cnum | snum | charge | name
------+------+------+--------+------
(0 rows)

そのような場合は、USING句を使用する。

USING

USING句は同じ名前と型のうち、結合の条件として使用する列を指定する。
NATURAL JOINと同様に同じである列は重複して表示しない。

SELECT 選択リスト FROM テーブル1 JOIN テーブル2 USING(列の並び);
oddtbs=> select * from g02 join c01 using(gnum);
 gnum | cnum | color | cnum | charge
------+------+-------+------+--------
    1 |  100 | 青    |    1 | 田中
    1 |  100 | 青    |    2 | 佐藤
    1 |  100 | 青    |    3 | 鈴木
    1 |  100 | 青    |    4 | 松井
    2 |  100 | 赤    |    1 | 岡田
    2 |  100 | 赤    |    2 | 山本
    2 |  100 | 赤    |    3 | 斎藤
    2 |  100 | 赤    |    4 | 吉田
    3 |  100 | 緑    |    1 | 村山
    3 |  100 | 緑    |    2 | 森田
    3 |  100 | 緑    |    3 | 原田
    3 |  100 | 緑    |    4 | 島田
(12 rows)

oddtbs=> select * from g02 join s01 using(gnum);
 gnum | cnum | color | cnum | snum |     name
------+------+-------+------+------+--------------
    1 |  100 | 青    |    1 |    1 | 大石友美
    1 |  100 | 青    |    1 |    2 | 中村優作
    1 |  100 | 青    |    1 |    3 | 北川陽子
    1 |  100 | 青    |    1 |    4 | 望月慎太郎
    1 |  100 | 青    |    1 |    5 | 木村葉子
    1 |  100 | 青    |    1 |    6 | 藤田智子
    1 |  100 | 青    |    2 |    1 | 石川大地
...
...
    3 |  100 | 緑    |    4 |    4 | 鷲山綾子
    3 |  100 | 緑    |    4 |    5 | 内山絢平
    3 |  100 | 緑    |    4 |    6 | 梶間昇平
(72 rows)

oddtbs=> select * from c02 join s01 using(gnum, cnum);
 gnum | cnum | snum | charge | snum |     name
------+------+------+--------+------+--------------
    1 |    1 |  200 | 田中   |    1 | 大石友美
    1 |    1 |  200 | 田中   |    2 | 中村優作
    1 |    1 |  200 | 田中   |    3 | 北川陽子
    1 |    1 |  200 | 田中   |    4 | 望月慎太郎
    1 |    1 |  200 | 田中   |    5 | 木村葉子
    1 |    1 |  200 | 田中   |    6 | 藤田智子
    1 |    2 |  200 | 佐藤   |    1 | 石川大地
...
...
    3 |    4 |  200 | 島田   |    4 | 鷲山綾子
    3 |    4 |  200 | 島田   |    5 | 内山絢平
    3 |    4 |  200 | 島田   |    6 | 梶間昇平
(72 rows)

NATURAL JOINもUSINGも使用できない例

結合の条件として使用したい列の中に、異なる名前のものが含まれる場合は、NATURAL JOINもUSING句も使用できない。
例えば次の結合など。

g03とc01
g03とs01
c03とs01

そのような場合はON句を使用する。

ON

ON句はWHEREと同様に任意の結合条件を指定できる。
ただし、NATURALでもCROSSでもないJOINはUSING句かON句が必要なので、全てをWHEREで代用することはできない。
ON句とWHERE句の併用は可能。通常は結合の条件はON句で、その他の条件はWHEREで指定する。
NATURAL JOINやON句とは異なり、同じである列も全て表示する。

SELECT 選択リスト FROM テーブル1 JOIN テーブル2 ON 結合条件;
oddtbs=> select * from g03 g join c01 c on g.num = c.gnum;
 num | color | gnum | cnum | charge
-----+-------+------+------+--------
   1 | 青    |    1 |    1 | 田中
   1 | 青    |    1 |    2 | 佐藤
   1 | 青    |    1 |    3 | 鈴木
   1 | 青    |    1 |    4 | 松井
   2 | 赤    |    2 |    1 | 岡田
   2 | 赤    |    2 |    2 | 山本
   2 | 赤    |    2 |    3 | 斎藤
   2 | 赤    |    2 |    4 | 吉田
   3 | 緑    |    3 |    1 | 村山
   3 | 緑    |    3 |    2 | 森田
   3 | 緑    |    3 |    3 | 原田
   3 | 緑    |    3 |    4 | 島田
(12 rows)

oddtbs=> select * from g03 g join s01 s on g.num = s.gnum;
num | color | gnum | cnum | snum |     name
----+-------+------+------+------+--------------
  1 | 青    |    1 |    1 |    1 | 大石友美
  1 | 青    |    1 |    1 |    2 | 中村優作
  1 | 青    |    1 |    1 |    3 | 北川陽子
  1 | 青    |    1 |    1 |    4 | 望月慎太郎
  1 | 青    |    1 |    1 |    5 | 木村葉子
  1 | 青    |    1 |    1 |    6 | 藤田智子
  1 | 青    |    1 |    2 |    1 | 石川大地
...
...
   3 | 緑    |    3 |    4 |    4 | 鷲山綾子
   3 | 緑    |    3 |    4 |    5 | 内山絢平
   3 | 緑    |    3 |    4 |    6 | 梶間昇平
(72 rows)

oddtbs=> select * from c03 c join s01 s on c.gnum = s.gnum and c.num = s.cnum;
 gnum | num | charge | gnum | cnum | snum |     name
------+-----+--------+------+------+------+--------------
    1 |   1 | 田中   |    1 |    1 |    1 | 大石友美
    1 |   1 | 田中   |    1 |    1 |    2 | 中村優作
    1 |   1 | 田中   |    1 |    1 |    3 | 北川陽子
    1 |   1 | 田中   |    1 |    1 |    4 | 望月慎太郎
    1 |   1 | 田中   |    1 |    1 |    5 | 木村葉子
    1 |   1 | 田中   |    1 |    1 |    6 | 藤田智子
...
...
    3 |   4 | 島田   |    3 |    4 |    4 | 鷲山綾子
    3 |   4 | 島田   |    3 |    4 |    5 | 内山絢平
    3 |   4 | 島田   |    3 |    4 |    6 | 梶間昇平
(72 rows)

oddtbs=> select * from c03 c join s01 s on (c.gnum, c.num) = (s.gnum, s.cnum);
結果は上と同じ。