SQL DML:結合(JOIN)
概要/結合方法
※複数のテーブルをくっつける。
その上でSELECTしたりする。
情報処理資格的に言うと「結合」
(1)テーブルを , で区切り、WHERE句で絞る
SELECT * FROM 表1, 表2
WHERE 表1.列 = 表2.列 AND ~
※WHERE句無しの場合:全組み合わせ表示
(「単純結合」参照)
(2)JOIN句で結合条件を指定
SELECT * FROM テーブル1
JOIN テーブル2 ON テーブル1.列1 = テーブル2.列2
等価結合_非等価結合
等価結合
自然結合、ON句、USING句を使用した結合時の条件に「=」を用いて列指定を行う結合。
非等価結合
ON句を使用した結合時の条件に「=」を用いない列指定を行う結合。
BETWEEN、IN、LIKE等のWHERE句に用いられる検索条件を利用できる。
特定の範囲で条件を指定する結合方法
給与テーブル
氏名 給与 級
伊藤 180,000 ?
田中 195,000 ?
白井 260,000 ?
等級テーブル
級 最低 最高
3 150,001 200,000
4 200,001 300,000
5 300,001 400,000
SELECT *
FROM 給与 JOIN 等級
ON 級 BETWEEN 最低 AND 最高
氏名 給与 等級
伊藤 180,000 3
田中 195,000 4
白井 260,000 4
内部結合
結合対象 列名 |
結合対象 列型 |
複数列 | 結合列の SELECT |
メリット | |
---|---|---|---|---|---|
NATURAL JOIN |
別名称× | 別型× (暗黙の型変換) |
強制AND条件 | 列修飾× | 記述が楽 |
JOIN USING |
別名称× | 別型× (暗黙の型変換) |
条件指定○ | 列修飾× | 表示列を減らせる |
JOIN ON |
別名称○ | 別型△ (明示的型変換) |
条件指定○ | 列修飾○ | 正確 |
INNER JOIN
結合対象の表(テーブル)、両方に共通するレコードのみを結合・抽出する結合方法
SELECT 生徒.*, テスト.*
FROM 生徒 INNER JOIN テスト
FROM 生徒 JOIN テスト ※INNERは省略可
ON 生徒.ID = テスト.ID
EMPNO | ENAME | DEPTNO |
1 | C# | 1 |
2 | C++ | 2 |
3 | VB.NET | 1 |
4 | VB6 | 1 |
5 | JAVA | 2 |
6 | JS | 3 |
7 | PERL | 3 |
↑↓を結合
DEPTNO | DNAME | BOSS |
1 | MicroSoft | 1 |
2 | Almighty | 2 |
3 | WEB | 3 |
↓ 結果
EMPNO | ENAME | DEPTNO | DNAME |
1 | C# | 1 | MicroSoft |
4 | VB6 | 1 | MicroSoft |
3 | VB.NET | 1 | MicroSoft |
5 | JAVA | 2 | Almighty |
2 | C++ | 2 | Almighty |
7 | PERL | 3 | WEB |
6 | JS | 3 | WEB |
USING句
USING 列名
↓と同じ
~ FROM (テーブル名1) JOIN (テーブル名2)
ON (テーブル名1).列名 = (テーブル名2).列名
SELECT *
FROM テーブル1 JOIN テーブル2
USING (列1)
※×:NATURAL JOIN ○:JOIN
USING句を使うのに適している場合
(自然結合と比較して)
・結合する表に同名で別型の列があり、自然結合するとエラーになってしまう場合
エラーとなる列を結合条件から外せる
・結合する表に同名でNULL許容の列があり、自然結合するとエラーになってしまう場合
FROM 表1
USING 表2
WHERE
表2 .列 = 表1 .列 --結合条件
AND ~ --条件他
外部結合
結合条件に一致するデータに加えて、結合対象の表(テーブル)、どちらか片方にだけあるレコードも抽出・結合する結合方法
このどちらか片方にだけある表の指定によって、
・LEFT OUTER JOIN
・RIGHT OUTER JOIN
のやり方がある。
※結合前テーブル
EMPNO | ENAME | DEPTNO |
1 | C# | 1 |
2 | C++ | (NULL) |
3 | VB.NET | 1 |
4 | VB6 | 1 |
5 | JAVA | 2 |
6 | JS | 3 |
7 | PERL | 3 |
DEPTNO | DNAME |
1 | MicroSoft |
2 | Almighty |
3 | WEB |
4 | Assembly |
左外部結合
SELECT E.EMPNO, E.ENAME, D.DEPTNO, D.DNAME
FROM EMPLOYEE E LEFT OUTER JOIN DEPARTMENT D ON E.DEPTNO = D.DEPTNO
ORDER BY E.EMPNO;
EMPNO | ENAME | DEPTNO | DNAME |
1 | C# | 1 | MicroSoft |
2 | C++ | (NULL) | (NULL) |
3 | VB.NET | 1 | MicroSoft |
4 | VB6 | 1 | MicroSoft |
5 | JAVA | 2 | Almighty |
6 | JS | 3 | WEB |
7 | PERL | 3 | WEB |
※左の表:EMPLOYEEのC++におけるDEPTNOは(NULL)で、
表:DEPARTMENTに該当するレコードは無いが、
結合後の表のDNAMEも(NULL)として表示している。
=左表のレコードは全て表示されている一方、右表のAssemblyのレコードは表示されていない。
右外部結合
SELECT E.EMPNO, E.ENAME, D.DEPTNO, D.DNAME
FROM EMPLOYEE E RIGHT OUTER JOIN DEPARTMENT D ON E.DEPTNO = D.DEPTNO
ORDER BY E.EMPNO;
EMPNO | ENAME | DEPTNO | DNAME |
1 | C# | 1 | MicroSoft |
3 | VB.NET | 1 | MicroSoft |
4 | VB6 | 1 | MicroSoft |
5 | JAVA | 2 | Almighty |
6 | JS | 3 | WEB |
7 | PERL | 3 | WEB |
(NULL) | (NULL) | 4 | Asesembly |
※左の列:EMPLOYEEにおいて、
右の表:DEPARTMENTのAssemblyをDEPTNO列に持つレコードは無いが、
結合後の表にはAssemblyレコードが表示されている。
=右表のレコードは全て表示されている一方、
左表のC++のレコードはDEPTNOを持たない為、表示されていない。
外部結合演算子(+)
※ ↓と同じ
FROM MYTABLE M INNER JOIN EMPLOYEE E ON M.ID = E.ID;
SELECT ~ FROM MYTABLE M, EMPLOYEE E WHERE M.ID(+) = E.ID;
※ ↓と同じ
FROM MYTABLE M RIGHT OUTER JOIN EMPLOYEE E ON M.ID = E.ID;
SELECT ~ FROM MYTABLE M, EMPLOYEE E WHERE M.ID = E.ID(+);
※ ↓と同じ
FROM MYTABLE M LEFT OUTER JOIN EMPLOYEE E ON M.ID = E.ID;
完全外部結合
・LEFT OUTER JOIN
・RIGHT OUTER JOIN
の両方
FROM EMPLOYEE E FULL OUTER JOIN DEPARTMENT D ON E.DEPTNO = D.DEPTNO
EMPNO | ENAME | DEPTNO | DNAME |
1 | C# | 1 | MicroSoft |
2 | C++ | (NULL) | (NULL) |
3 | VB.NET | 1 | MicroSoft |
4 | VB6 | 1 | MicroSoft |
5 | JAVA | 2 | Almighty |
6 | JS | 3 | WEB |
7 | PERL | 3 | WEB |
(NULL) | (NULL) | 4 | Asesembly |
左外部結合では表示されなかったAssemblyのレコードが、
右外部結合では表示されなかったC++のレコードが表示される。
自然結合
自己結合
1つの表内で論理的な複数の表を作成した上で、それぞれを結合する結合
※①元テーブル
EMPNO | ENAME | BOSS |
1 | C# | 1 |
2 | C++ | 2 |
3 | VB.NET | 1 |
4 | VB6 | 1 |
5 | JAVA | 2 |
6 | JS | 7 |
7 | PERL | 7 |
※②元テーブル内のBOSSを抽出したテーブル
EMPNO | ENAME |
1 | C# |
2 | C++ |
7 | PERL |
※①と②をBOSS = EMPNOで結合
SELECT E.EMPNO, E.ENAME, E.BOSS, B.ENAME BOSSNAME
FROM EMPLOYEE E LEFT OUTER JOIN EMPLOYEE B
ON E.BOSS = B.EMPNO
EMPNO | ENAME | BOSS | BOSSNAME |
1 | C# | 1 | C# |
2 | C++ | 2 | C++ |
3 | VB.NET | 1 | C# |
4 | VB6 | 1 | C# |
5 | JAVA | 2 | C++ |
6 | JS | 7 | PERL |
7 | PERL | 7 | PERL |
単純結合
別名:直積結合/クロス結合
デカルト積(直積)が生成される。
SELECT *
FROM テーブル1 CROSS JOIN テーブル1
↓と同じ
(1)SELECT * FROM テーブル1, テーブル2
(2)SELECT * FROM テーブル1 NATURAL JOIN テーブル2
※共通列無しの場合
(3)SELECT * FROM テーブル1 (INNER) JOIN テーブル2
※結合条件無し
(4)SELECT * FROM テーブル1 (INNER) JOIN テーブル2
ON テーブル1.列 = テーブル1.列
※無意味な結合条件
速度改善
SELECT * FROM テスト JOIN (SELECT * 生徒 WHERE 性別 = 男) AS 男生徒
ON 男生徒.NO = テスト.NO
※男だけに絞った生徒テーブルとテストをNO列の条件で結合(結合行が少ない)
SELECT * FROM テスト JOIN 生徒
ON 生徒.NO = テスト.NO
WHERE 性別 = 男
※両テーブルにおけるNO列の条件で全件結合した後、男だけに絞る(結合行が多い)
結合した列を更新
(
SELECT 列 FROM 表1 JOIN 表2 ON ~
)
SET 列 = '値'