SQL道場 テーブル(表)とテーブル(表)を結合する方法

テーブル同士の結合を行うINNER JOIN句(内部結合)、外部結合を行うLEFT OUTER JOIN句(左側外部結合)、RIGHT OUTER JOIN句(右側外部結合)、FULL OUTER JOIN句(完全外部結合)、自己結合の使用方法を解説。

環境

使用ツール:Microsoft SQL Server Management Studio MySQL Workbench

テーブル設計図

SQLServer

ER図

MySQL

内部結合(INNER JOIN句)

対応:SQL Server MySQL Oracle PostgreSQL DB2 Access ANSI

基本

内部結合を行うことにより結合列の値が一致する行を1行にして表示します。例えば、得意先マスタテーブルと売上テーブルがあったとして、売上テーブルの得意先CDと得意先マスタテーブルの得意先CDがマッチしたレコードを結合して表示します。主にテーブル間の関係が1対1の関係が成り立っているときに使用します。1対1の関係が成り立っていない場合は、重複のレコードが返されます。

SELECT文の中にいくつでも「INNER JOIN句」を使用することができます。また、結合条件はON句の後に指定します。結合条件は「AND演算子」や「OR演算子」で複数指定することができます。「INNER JOIN句」を使用した場合、FROM句や「INNER JOIN句」の後に指定するテーブル名に別名を付けます。別名は必ず指定する必要はありませんが一般的には別名を指定します。また、複数テーブルを結合する場合、テーブル名が重複してエラーを起こすこともありますので、別名は付けたほうがベターです。

INNER JOIN解説図

構文

/* 全列表示 */
SELECT 
    * 
FROM テーブル名 AS 表名1
INNER JOIN 表名2 ON 表名1.結合列 = 表名2.結合列
;
/* 特定列のみ表示 */
SELECT 
    表名1.カラム,
    表名2.カラム,
   ・
   ・
   ・
FROM テーブル名 AS 表名1
INNER JOIN 表名2 ON 表名1.結合列 = 表名2.結合列
;

ON句の条件の後に、データを絞り込むための条件を指定することもできます。

SELECT 
    * 
FROM テーブル名 AS 表名1
INNER JOIN 表名2 ON 表名1.結合列 = 表名2.結合列 AND 表名1.列 = 値
;

実行結果

「DT_PROCEEDS(売上テーブル)」と「MST_CUSTOME(得意先マスタテーブル)」を得意先CDで内部結合して、売上テーブルに存在するレコード+得意先レコードを結合して出力するサンプルになります。

得意先マスタテーブル

IDCT_NAME
(得意先名)
CT_NAME_KANA
(得意先カナ)
CT_ZIPCD
(郵便番号)
CT_ADDRESS
(住所)
CT_TEL
(電話番号)
CT_ESTABLISHMENT
(設立日)
CT_FAX
(FAX番号)
ENABLE
(有効区分)
1すなりん商事すなりんしょうじ9999999東京都町田市0306669992020-01-010306669981
2浜田株式会社はまだかぶしきかいしゃ9999998茨木県都杉並町02922299991990-01-0102922299981
3ほしの有限会社ほしのゆうげんかいしゃ9999997青森県青森市01799911111800-12-1501799911101
4いかぶし株式会社いかぶしかぶしきかいしゃ9999996福岡県糸田町09479911112000-09-0109479911101
5さめはだ有限会社さめはだゆうげんかいしゃ9999995沖縄県那覇市09899911112021-05-2309899911101

売上テーブル

SLIPNO
(伝票番号)
EMP_ID
(担当者CD)
CT_ID
(得意先CD)
PR_ORDERDATE
(受注日)
PR_PRODUCT_CD
(商品CD)
PR_PRODUCT_NAME
(商品名)
PR_UNITPRICE
(単価)
PR_QUANITY
(数量)
PR_TAX
(消費税)
PR_TOTAL
(合計金額)
ENABLE
(有効区分)
11112022-12-20100湯沸器5000150065001
22222022-12-21200ガス検知器200002000220001

SQL Server

/* 得意先マスタテーブルと売上テーブルを内部結合 */
SELECT 
    *
FROM [SampleDB].[dbo].[DT_PROCEEDS] AS DT_PROCEEDS
INNER JOIN [SampleDB].[dbo].[MST_CUSTOME] AS MST_CUSTOME ON DT_PROCEEDS.CT_ID = MST_CUSTOME.ID;
INNER JOIN実行結果:SQLServer

MySQL

/* 得意先マスタテーブルと売上テーブルを内部結合 */
SELECT 
    *
FROM testdb.DT_PROCEEDS AS DT_PROCEEDS
INNER JOIN testdb.MST_CUSTOME AS MST_CUSTOME ON DT_PROCEEDS.CT_ID = MST_CUSTOME.ID;
INNER JOIN実行結果:MySQL

特定の条件にマッチするレコード抽出

「DT_PROCEEDS(売上テーブル)」と「MST_CUSTOME(得意先マスタテーブル)」を得意先CDで内部結合して、売上テーブルに存在するレコード+得意先レコードを結合して出力します。さらにINNER JOIN句に対してWHERE句的な使用方法ができます。ここでは、売上テーブルから有効区分が有効なレコードのみ抽出しています。

表示結果は、伝票番号1のレコードが表示されます。

「DT_PROCEEDS(売上テーブル)」と「MST_CUSTOME(得意先マスタテーブル)」を得意先CDで内部結合して、売上テーブルに存在するレコード+得意先レコードを結合して出力します。さらにINNER JOIN句に対してWHERE句的な使用方法ができます。ここでは、売上テーブルから有効区分が有効なレコードのみ抽出しています。
表示結果は、伝票番号1のレコードが表示されます。

得意先マスタテーブル

IDCT_NAME
(得意先名)
CT_NAME_KANA
(得意先カナ)
CT_ZIPCD
(郵便番号)
CT_ADDRESS
(住所)
CT_TEL
(電話番号)
CT_ESTABLISHMENT
(設立日)
CT_FAX
(FAX番号)
ENABLE
(有効区分)
1すなりん商事すなりんしょうじ9999999東京都町田市0306669992020-01-010306669981
2浜田株式会社はまだかぶしきかいしゃ9999998茨木県都杉並町02922299991990-01-0102922299981
3ほしの有限会社ほしのゆうげんかいしゃ9999997青森県青森市01799911111800-12-1501799911101
4いかぶし株式会社いかぶしかぶしきかいしゃ9999996福岡県糸田町09479911112000-09-0109479911101
5さめはだ有限会社さめはだゆうげんかいしゃ9999995沖縄県那覇市09899911112021-05-2309899911101

売上テーブル

SLIPNO
(伝票番号)
EMP_ID
(担当者CD)
CT_ID
(得意先CD)
PR_ORDERDATE
(受注日)
PR_PRODUCT_CD
(商品CD)
PR_PRODUCT_NAME
(商品名)
PR_UNITPRICE
(単価)
PR_QUANITY
(数量)
PR_TAX
(消費税)
PR_TOTAL
(合計金額)
ENABLE
(有効区分)
1112022-12-20100湯沸器50003150065001
2222022-12-21200ガス検知器2000012000220000

SQL Server

/* 得意先マスタテーブルと売上テーブルを内部結合 */
SELECT 
    *
FROM [SampleDB].[dbo].[DT_PROCEEDS] AS DT_PROCEEDS
INNER JOIN [SampleDB].[dbo].[MST_CUSTOME] AS MST_CUSTOME 
	ON DT_PROCEEDS.CT_ID = MST_CUSTOME.ID 
		AND DT_PROCEEDS.ENABLE = '1';
特定の条件にマッチするINNER JOIN実行結果:SQLServer

MySQL

/* 得意先マスタテーブルと売上テーブルを内部結合 */
SELECT 
    *
FROM testdb.DT_PROCEEDS AS DT_PROCEEDS
INNER JOIN testdb.MST_CUSTOME AS MST_CUSTOME 
	ON DT_PROCEEDS.CT_ID = MST_CUSTOME.ID 
		AND DT_PROCEEDS.ENABLE = '1';
特定の条件にマッチするINNER JOIN実行結果:MySQL

特定のカラムのみ表示する

*(アスタリスク)を使用するとすべての列が表示されてしまい可読性が悪いときがあります。その時は、特定の列のみ表示することができます。

得意先マスタテーブル

IDCT_NAME
(得意先名)
CT_NAME_KANA
(得意先カナ)
CT_ZIPCD
(郵便番号)
CT_ADDRESS
(住所)
CT_TEL
(電話番号)
CT_ESTABLISHMENT
(設立日)
CT_FAX
(FAX番号)
ENABLE
(有効区分)
1すなりん商事すなりんしょうじ9999999東京都町田市0306669992020-01-010306669981
2浜田株式会社はまだかぶしきかいしゃ9999998茨木県都杉並町02922299991990-01-0102922299981
3ほしの有限会社ほしのゆうげんかいしゃ9999997青森県青森市01799911111800-12-1501799911101
4いかぶし株式会社いかぶしかぶしきかいしゃ9999996福岡県糸田町09479911112000-09-0109479911101
5さめはだ有限会社さめはだゆうげんかいしゃ9999995沖縄県那覇市09899911112021-05-2309899911101

売上テーブル

SLIPNO
(伝票番号)
EMP_ID
(担当者CD)
CT_ID
(得意先CD)
PR_ORDERDATE
(受注日)
PR_PRODUCT_CD
(商品CD)
PR_PRODUCT_NAME
(商品名)
PR_UNITPRICE
(単価)
PR_QUANITY
(数量)
PR_TAX
(消費税)
PR_TOTAL
(合計金額)
ENABLE
(有効区分)
1112022-12-20100湯沸器50003150065001
2222022-12-21200ガス検知器2000012000220000

SQL Server

/* 得意先マスタテーブルと売上テーブルを内部結合 */
SELECT 
   DT_PROCEEDS.SLIPNO
	,MST_CUSTOME.CT_NAME
   ,DT_PROCEEDS.PR_PRODUCT_NAME 
FROM [SampleDB].[dbo].[DT_PROCEEDS] AS DT_PROCEEDS
INNER JOIN [SampleDB].[dbo].[MST_CUSTOME] AS MST_CUSTOME 
	ON DT_PROCEEDS.CT_ID = MST_CUSTOME.ID 
;
特定のカラムを表示するINNER JOIN実行結果:SQLServer

MySQL

/* 得意先マスタテーブルと売上テーブルを内部結合 */
SELECT 
    DT_PROCEEDS.SLIPNO
	,MST_CUSTOME.CT_NAME
    ,DT_PROCEEDS.PR_PRODUCT_NAME
FROM testdb.DT_PROCEEDS AS DT_PROCEEDS
INNER JOIN testdb.MST_CUSTOME AS MST_CUSTOME 
	ON DT_PROCEEDS.CT_ID = MST_CUSTOME.ID 
;
特定のカラムを表示するINNER JOIN実行結果:MySQL

左側外部結合(LEFT OUTER JOIN句)

対応:SQL Server MySQL Oracle PostgreSQL DB2 Access ANSI

基本

「LEFT OUTER JOIN」は2つのテーブルをキーで結合します。INNER JOIN句(内部結合)と異なる点は、FROMで指定したテーブルは全レコードが表示されます。LEFT OUTER JOINは、FROM句で指定したテーブルにマッチする結合条件のみレコードを結合します。

また、LEFT OUTER JOIN句とFROM句で指定したテーブルにマッチしない場合でも、FROM句側のテーブルのレコードは全件表示します。その場合、FROM句側のテーブルとマッチしないLEFT OUTER JOIN側の列はNULLで表示されます。

LEFT OUTER JOINの解説図

構文

SELECT 
    * 
FROM テーブル名 AS 表名1
LEFT OUTER JOIN 表名2 ON 表名1.結合列 = 表名2.結合列
;

SELECT 
    * 
FROM テーブル名 AS 表名1
LEFT JOIN 表名2 ON 表名1.結合列 = 表名2.結合列
;

AND演算子やOR演算子を使用して、条件をいくつも足していくことができます。

SELECT 
    * 
FROM テーブル名 AS 表名1
LEFT OUTER JOIN 表名2 ON 表名1.結合列 = 表名2.結合列 AND 条件式 = 条件式 OR 条件式 = 条件式
;

Oracle

ORACLEデータベースの場合は、「+」演算子を使用してLEFT OUTER JOINを指定することができます。「+」演算子は、WHERE句で指定したカラムの右側に付けます。


SELECT 
    * 
FROM テーブル名1,テーブル名2
WHERE テーブル名1.カラム= テーブル名2.カラム(+) 
;

実行結果

「LEFT OUTER JOIN句」で「DT_PROCEEDS(売上テーブル)」と「MST_CUSTOME(得意先マスタテーブル)」を得意先CDで結合しています。DT_PROCEEDS(売上テーブル)側のレコードは全件表示され、LEFT OUTER JOIN句側のテーブルで結合するレコードがない列はNULLで表示されます。

得意先マスタテーブル

IDCT_NAME
(得意先名)
CT_NAME_KANA
(得意先カナ)
CT_ZIPCD
(郵便番号)
CT_ADDRESS
(住所)
CT_TEL
(電話番号)
CT_ESTABLISHMENT
(設立日)
CT_FAX
(FAX番号)
ENABLE
(有効区分)
1すなりん商事すなりんしょうじ9999999東京都町田市0306669992020-01-010306669981
2浜田株式会社はまだかぶしきかいしゃ9999998茨木県都杉並町02922299991990-01-0102922299981
3ほしの有限会社ほしのゆうげんかいしゃ9999997青森県青森市01799911111800-12-1501799911101
4いかぶし株式会社いかぶしかぶしきかいしゃ9999996福岡県糸田町09479911112000-09-0109479911101
5さめはだ有限会社さめはだゆうげんかいしゃ9999995沖縄県那覇市09899911112021-05-2309899911101

売上テーブル

SLIPNO
(伝票番号)
EMP_ID
(担当者CD)
CT_ID
(得意先CD)
PR_ORDERDATE
(受注日)
PR_PRODUCT_CD
(商品CD)
PR_PRODUCT_NAME
(商品名)
PR_UNITPRICE
(単価)
PR_QUANITY
(数量)
PR_TAX
(消費税)
PR_TOTAL
(合計金額)
ENABLE
(有効区分)
1112022-12-20100湯沸器50003150065001
2222022-12-21200ガス検知器2000012000220000
3262022-12-10300加工品1000011000110001

SQL Server

/* LEFT OUTER JOIN */
SELECT 
*
FROM [SampleDB].[dbo].[DT_PROCEEDS] AS DT_PROCEEDS
LEFT OUTER JOIN [SampleDB].[dbo].[MST_CUSTOME] AS MST_CUSTOME 
	ON DT_PROCEEDS.CT_ID = MST_CUSTOME.ID
;
LEFT OUTER JOIN実行結果:SQLServer

MySQL

/* LEFT OUTER JOIN */
SELECT 
*
FROM testdb.DT_PROCEEDS AS DT_PROCEEDS
LEFT OUTER JOIN testdb.MST_CUSTOME AS MST_CUSTOME 
	ON DT_PROCEEDS.CT_ID = MST_CUSTOME.ID
;
LEFT OUTER JOIN実行結果:MySQL

右側外部結合(RIGHT OUTER JOIN句)

対応:SQL Server MySQL Oracle PostgreSQL DB2 Access ANSI

基本

「RIGHT OUTER JOIN句」は2つのテーブルをキーで結合します。「INNER JOIN句(内部結合)」、「LEFT OUTER JOIN句」と異なる点は、「RIGHT OUTER JOIN句」で指定したテーブルはすべてレコードが表示されます。FROM句側のテーブルは、指定した条件にマッチする結合条件のみレコードが結合されます。

また、「RIGHT OUTER JOIN句」とFROM句で指定した条件にマッチしない場合、その場合、FROM句側の列はNULLで表示されます。

RIGHT OUTER JOINの解説図

構文

SELECT 
    * 
FROM テーブル名 AS 表名1
RIGHT OUTER JOIN 表名2 ON 表名1.結合列 = 表名2.結合列
;

SELECT 
    * 
FROM テーブル名 AS 表名1
RIGHT JOIN 表名2 ON 表名1.結合列 = 表名2.結合列
;

AND演算子やOR演算子を使用して、条件をいくつも足していくことができます。

SELECT 
    * 
FROM テーブル名 AS 表名1
RIGHT OUTER JOIN 表名2 ON 表名1.結合列 = 表名2.結合列 AND 条件式 = 条件式 OR 条件式 = 条件式
;

Oracle

ORACLEデータベースの場合は、「+」演算子を使用してRIGHT OUTER JOINを指定することができます。「+」演算子は、WHERE句で指定したカラムの左側に付けます。

SELECT 
    * 
FROM テーブル名1,テーブル名2
WHERE テーブル名1.カラム(+) = テーブル名2.カラム
;

実行結果

「DT_PROCEEDS(売上テーブル)」と「MST_CUSTOME(得意先マスタテーブル)」を得意先CDで結合して、得意先マスタテーブルが全件表示され売上テーブルは得意先マスタテーブルのIDとマッチするレコードだけ結合されます。

得意先マスタテーブル

IDCT_NAME
(得意先名)
CT_NAME_KANA
(得意先カナ)
CT_ZIPCD
(郵便番号)
CT_ADDRESS
(住所)
CT_TEL
(電話番号)
CT_ESTABLISHMENT
(設立日)
CT_FAX
(FAX番号)
ENABLE
(有効区分)
1すなりん商事すなりんしょうじ9999999東京都町田市0306669992020-01-010306669981
2浜田株式会社はまだかぶしきかいしゃ9999998茨木県都杉並町02922299991990-01-0102922299981
3ほしの有限会社ほしのゆうげんかいしゃ9999997青森県青森市01799911111800-12-1501799911101
4いかぶし株式会社いかぶしかぶしきかいしゃ9999996福岡県糸田町09479911112000-09-0109479911101
5さめはだ有限会社さめはだゆうげんかいしゃ9999995沖縄県那覇市09899911112021-05-2309899911101

売上テーブル

SLIPNO
(伝票番号)
EMP_ID
(担当者CD)
CT_ID
(得意先CD)
PR_ORDERDATE
(受注日)
PR_PRODUCT_CD
(商品CD)
PR_PRODUCT_NAME
(商品名)
PR_UNITPRICE
(単価)
PR_QUANITY
(数量)
PR_TAX
(消費税)
PR_TOTAL
(合計金額)
ENABLE
(有効区分)
1112022-12-20100湯沸器50003150065001
2222022-12-21200ガス検知器2000012000220000
3262022-12-10300加工品1000011000110001

SQL Server

/* RIGHT OUTER JOIN */
SELECT 
*
FROM [SampleDB].[dbo].[DT_PROCEEDS] AS DT_PROCEEDS
RIGHT OUTER JOIN [SampleDB].[dbo].[MST_CUSTOME] AS MST_CUSTOME 
	ON DT_PROCEEDS.CT_ID = MST_CUSTOME.ID
;
RIGHT OUTER JOIN実行結果:SQLServer

MySQL

/* RIGHT OUTER JOIN */
SELECT 
*
FROM testdb.DT_PROCEEDS AS DT_PROCEEDS
RIGHT OUTER JOIN testdb.MST_CUSTOME AS MST_CUSTOME 
	ON DT_PROCEEDS.CT_ID = MST_CUSTOME.ID
;
RIGHT OUTER JOIN実行結果:MySQL

完全外部結合(FULL OUTER JOIN句)

対応:SQL Server

基本

「FULL OUTER JOIN句」は両方のテーブルにない場合でもすべてレコードを結合して表示します。結合できない列はNULLで表示されます。

FULL OUTER JOIN解説図

構文

SELECT 
    * 
FROM テーブル名 AS 表名1
FULL OUTER JOIN 表名2 ON 表名1.結合列 = 表名2.結合列
;

SELECT 
    * 
FROM テーブル名 AS 表名1
FULL JOIN 表名2 ON 表名1.結合列 = 表名2.結合列
;

実行結果

「DT_PROCEEDS(売上テーブル)」と「MST_CUSTOME(得意先マスタテーブル)」を得意先CDで結合して、得意先マスタテーブルが全件表示され売上テーブルは得意先マスタテーブルのIDとマッチするレコードだけ結合されます。

得意先マスタテーブル

IDCT_NAME
(得意先名)
CT_NAME_KANA
(得意先カナ)
CT_ZIPCD
(郵便番号)
CT_ADDRESS
(住所)
CT_TEL
(電話番号)
CT_ESTABLISHMENT
(設立日)
CT_FAX
(FAX番号)
ENABLE
(有効区分)
1すなりん商事すなりんしょうじ9999999東京都町田市0306669992020-01-010306669981
2浜田株式会社はまだかぶしきかいしゃ9999998茨木県都杉並町02922299991990-01-0102922299981
3ほしの有限会社ほしのゆうげんかいしゃ9999997青森県青森市01799911111800-12-1501799911101
4いかぶし株式会社いかぶしかぶしきかいしゃ9999996福岡県糸田町09479911112000-09-0109479911101
5さめはだ有限会社さめはだゆうげんかいしゃ9999995沖縄県那覇市09899911112021-05-2309899911101

売上テーブル

SLIPNO
(伝票番号)
EMP_ID
(担当者CD)
CT_ID
(得意先CD)
PR_ORDERDATE
(受注日)
PR_PRODUCT_CD
(商品CD)
PR_PRODUCT_NAME
(商品名)
PR_UNITPRICE
(単価)
PR_QUANITY
(数量)
PR_TAX
(消費税)
PR_TOTAL
(合計金額)
ENABLE
(有効区分)
1112022-12-20100湯沸器50003150065001
2222022-12-21200ガス検知器2000012000220000
3262022-12-10300加工品1000011000110001

SQL Server

/* FULL OUTER JOIN */
SELECT 
*
FROM [SampleDB].[dbo].[DT_PROCEEDS] AS DT_PROCEEDS
FULL OUTER JOIN [SampleDB].[dbo].[MST_CUSTOME] AS MST_CUSTOME 
	ON DT_PROCEEDS.CT_ID = MST_CUSTOME.ID
;
FULL OUTER JOIN実行結果:SQLServer

自己結合

対応:SQL Server MySQL Oracle PostgreSQL DB2 Access ANSI

基本

テーブル結合は、別々のテーブル同士だけではなく同一テーブル同士も結合することができます。

自己結合解説図

構文

SELECT * FROM テーブル1 別名1,テーブル1 別名2 WHERE 別名1.カラム = 別名2.カラム;

実行結果

社員マスタテーブルから社員の上司を自己結合によって表示する例になります。EMP_BOSSCDと社員ID(ID)を結合することで社員の上司のレコードが結合されます。

ID

EMP_BOSSCD

(上司CD)

EMP_NAME(社員名)EMP_NAME_KANA(社員カナ)EMP_DEPTCD(部署コード)EMP_AGE(年齢)EMP_SEX(性別)ENABLE(有効区分)
1NULLすなりん 太郎すなりん たろう1351
2NULL博多 ぴーちはかた ぴーち2201
32田中 工事たなか こうじ2261
41佐々木 花子ささき はなこ1401
51佐藤 じゅんさとう じゅん1231
61佐々木 ゆんささき ゆん1231

SQL Server

/* 自己結合 */
SELECT 
*
FROM [SampleDB].[dbo].[MST_EMPLOYEE] AS [MST_EMPLOYEE],[SampleDB].[dbo].[MST_EMPLOYEE] AS EMP_BOSS
WHERE MST_EMPLOYEE.ID = EMP_BOSS.EMP_BOSSCD
;
自己結合実行結果:SQLServer

MySQL

/* 自己結合 */
SELECT 
*
FROM testdb.MST_EMPLOYEE AS MST_EMPLOYEE,testdb.MST_EMPLOYEE AS EMP_BOSS
WHERE MST_EMPLOYEE.ID = EMP_BOSS.EMP_BOSSCD
;
自己結合実行結果:MySQL