INNER JOIN(内部結合)は、テーブルとテーブルを結合するためのSQL文です。
/* テーブルA +----+------+-------+----------+------+---------+ | ID | Name | Class | Japanese | Math | English | +----+------+-------+----------+------+---------+ | 1 | 佐藤 | A | 100 | 100 | 85 | | 2 | 鈴木 | A | 90 | 70 | 70 | | 3 | 高橋 | A | 85 | 70 | 65 | | 4 | 中村 | A | 90 | 65 | 85 | | 5 | 小林 | B | 70 | 90 | 65 | | 6 | 山口 | B | 90 | 85 | 85 | | 7 | 田中 | B | 70 | 90 | 65 | | 8 | 伊藤 | B | 70 | 90 | 65 | +----+------+-------+----------+------+---------+ */ /* テーブルB +----+------+-------+---------+---------------+ | ID | Name | Class | Science | SocialStudies | +----+------+-------+---------+---------------+ | 1 | 佐藤 | A | 90 | 75 | | 2 | 鈴木 | A | 90 | 70 | | 3 | 高橋 | A | 85 | 70 | | 4 | 中村 | A | 40 | 0 | +----+------+-------+---------+---------------+ */ SELECT A.ID, A.Name, A.Class, A.Japanese, A.Math, A.English, B.Science, B.SocialStudies FROM PointList AS A INNER JOIN SubPointList AS B ON A.ID = B.ID; /* 結果 +----+------+-------+----------+------+---------+---------+---------------+ | ID | Name | Class | Japanese | Math | English | Science | SocialStudies | +----+------+-------+----------+------+---------+---------+---------------+ | 1 | 佐藤 | A | 100 | 100 | 85 | 90 | 75 | | 2 | 鈴木 | A | 90 | 70 | 70 | 90 | 70 | | 3 | 高橋 | A | 85 | 70 | 65 | 85 | 70 | | 4 | 中村 | A | 90 | 65 | 85 | 40 | 0 | +----+------+-------+----------+------+---------+---------+---------------+ */
複数のテーブルからほしい情報を取得し、1つの結果として表示したい場合に用います。
テーブル結合には大きく分類すると内部結合と外部結合―。2種類の結合パターンが存在しますが、本ページでは内部結合(INNER JOIN)について解説しています。
このページではSQL初心者向けにCASE文の利用方法をわかりやすく丁寧に図解付き・サンプルコード付きで解説します。
データベースエンジニアを目指す方であれば知らないと恥ずかしい超・基本知識です。是非最後までご覧ください。
SQL文の基本ルール(大文字/小文字の区別、コメントの付与など)を始めに学んでおきたい方は以下の記事を先にご覧ください。
INNER JOIN:内部結合とは?
INNER JOIN(内部結合)はテーブルとテーブルを結合する際に用います。
1つのテーブルだけでは情報が不足しているような場合に、他のテーブルのデータの情報も併せて表示したい場合などに用います。
早速構文ルールを確認していきます。
INNER JOIN:構文ルール
今回は実際にサンプルとなるテーブルを用意し、どのようにINNER JOIN(内部結合)の処理が行われるか?を確認していきましょう。
実際に自分で動かしてみたいという方のために、テーブルのCREATE文とレコード登録のためのINSERT文を掲載しておきます。
テーブル定義:参考(CREATE TABLE)
-- テーブルA CREATE TABLE PointList ( ID INT(3) NOT NULL PRIMARY KEY, Name VARCHAR(50) NOT NULL, Class VARCHAR(1), Japanese INT(3) DEFAULT '0', Math INT(3) DEFAULT '0', English INT(3) DEFAULT '0' ); /* +----------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+-------------+------+-----+---------+-------+ | ID | int(3) | NO | PRI | NULL | | | Name | varchar(50) | NO | | NULL | | | Class | varchar(1) | YES | | NULL | | | Japanese | int(3) | YES | | 0 | | | Math | int(3) | YES | | 0 | | | English | int(3) | YES | | 0 | | +----------+-------------+------+-----+---------+-------+ */ -- テーブルB CREATE TABLE SubPointList ( ID INT(3) NOT NULL PRIMARY KEY, Name VARCHAR(50) NOT NULL, Class VARCHAR(1), Science INT(3) DEFAULT '0', SocialStudies INT(3) DEFAULT '0' ); /* +---------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------------+-------------+------+-----+---------+-------+ | ID | int(3) | NO | PRI | NULL | | | Name | varchar(50) | NO | | NULL | | | Class | varchar(1) | YES | | NULL | | | Science | int(3) | YES | | 0 | | | SocialStudies | int(3) | YES | | 0 | | +---------------+-------------+------+-----+---------+-------+ */
利用するダミーレコード:参考(INSERT文)
INSERT INTO PointList (ID,Name,Class,Japanese,Math,English) VALUES (1,'佐藤','A',100,100,85); INSERT INTO PointList (ID,Name,Class,Japanese,Math,English) VALUES (2,'鈴木','A',90,70,70); INSERT INTO PointList (ID,Name,Class,Japanese,Math,English) VALUES (3,'高橋','A',85,70,65); INSERT INTO PointList (ID,Name,Class,Japanese,Math,English) VALUES (4,'中村','A',90,65,85); INSERT INTO PointList (ID,Name,Class,Japanese,Math,English) VALUES (5,'小林','B',70,90,65); INSERT INTO PointList (ID,Name,Class,Japanese,Math,English) VALUES (6,'山口','B',90,85,85); INSERT INTO PointList (ID,Name,Class,Japanese,Math,English) VALUES (7,'田中','B',70,90,65); INSERT INTO PointList (ID,Name,Class,Japanese,Math,English) VALUES (8,'伊藤','B',70,90,65); -- テーブルA確認 SELECT * FROM PointList; /* +----+------+-------+----------+------+---------+ | ID | Name | Class | Japanese | Math | English | +----+------+-------+----------+------+---------+ | 1 | 佐藤 | A | 100 | 100 | 85 | | 2 | 鈴木 | A | 90 | 70 | 70 | | 3 | 高橋 | A | 85 | 70 | 65 | | 4 | 中村 | A | 90 | 65 | 85 | | 5 | 小林 | B | 70 | 90 | 65 | | 6 | 山口 | B | 90 | 85 | 85 | | 7 | 田中 | B | 70 | 90 | 65 | | 8 | 伊藤 | B | 70 | 90 | 65 | +----+------+-------+----------+------+---------+ */ INSERT INTO SubPointList (ID,Name,Class,Science,SocialStudies) VALUES (1,'佐藤','A',90,75); INSERT INTO SubPointList (ID,Name,Class,Science,SocialStudies) VALUES (2,'鈴木','A',90,70); INSERT INTO SubPointList (ID,Name,Class,Science,SocialStudies) VALUES (3,'高橋','A',85,70); INSERT INTO SubPointList (ID,Name,Class,Science,SocialStudies) VALUES (4,'中村','A',40,0); -- テーブルB確認 SELECT * FROM SubPointList; +----+------+-------+---------+---------------+ | ID | Name | Class | Science | SocialStudies | +----+------+-------+---------+---------------+ | 1 | 佐藤 | A | 90 | 75 | | 2 | 鈴木 | A | 90 | 70 | | 3 | 高橋 | A | 85 | 70 | | 4 | 中村 | A | 40 | 0 | +----+------+-------+---------+---------------+
INNER JOIN:サンプルコード
2つのテーブルを "ID列" を結合キーとしてINNER JOIN(内部結合)した結果がこちらです。
SELECT A.ID, A.Name, A.Class, A.Japanese, A.Math, A.English, B.Science, B.SocialStudies FROM PointList AS A INNER JOIN SubPointList AS B ON A.ID = B.ID; /* 結果 +----+------+-------+----------+------+---------+---------+---------------+ | ID | Name | Class | Japanese | Math | English | Science | SocialStudies | +----+------+-------+----------+------+---------+---------+---------------+ | 1 | 佐藤 | A | 100 | 100 | 85 | 90 | 75 | | 2 | 鈴木 | A | 90 | 70 | 70 | 90 | 70 | | 3 | 高橋 | A | 85 | 70 | 65 | 85 | 70 | | 4 | 中村 | A | 90 | 65 | 85 | 40 | 0 | +----+------+-------+----------+------+---------+---------+---------------+ */
内部結合のポイントは大きく2つ。
内部結合のポイント①:結合キーが両テーブルに存在する場合のみ出力
INNER JOIN(内部結合)では、ON句で指定した結合キーが両方のテーブルに存在する場合にのみ結合が行われるということがポイントの1つ目。
わかりやすく示すと、以下の図でいえば両方のテーブルにある「役職A」と「役職B」のレコードのみが結合されるということです。
内部結合のポイント②:SELECT句は「テーブル名.カラム名」の形で記述
先ほどのSQL文のSELECT句をもう一度確認してみましょう。
SELECT A.ID, A.Name, A.Class, A.Japanese, A.Math, A.English, B.Science, B.SocialStudies FROM PointList AS A INNER JOIN SubPointList AS B ON A.ID = B.ID;
「テーブル名.カラム名」の形で記述していることが分かります。
これは、両方のテーブルに同じカラム名(例 ID,Name,Class)が存在しているため、その記述の曖昧さを避けるための措置です。(=どちらのテーブルのカラム名を表示すればよいか?をシステムが判断することができなくなってしまう。)
-- ID,Name,Classは結合対象の両方のテーブルに含まれるためエラーになる SELECT ID,Name,Class,Japanese,Science FROM PointList INNER JOIN SubpointList ON PointList.ID = SubpointList.ID; -- ERROR 1052 (23000): Column 'ID' in field list is ambiguous
したがって、片方のテーブルのみに存在するレコードを利用する場合は、厳密に「テーブル名.カラム名」の形で記述する必要はありません。
ただし、JOINを用いる場合には、SQLを読みやすくするために基本的に「テーブル名.カラム名」の形で記述することが一般的です。
SELECT句にワイルドカード「*」を利用すると以下のように両方のテーブルに存在するすべてのカラムが取得対象となります。
SELECT * FROM PointList AS A INNER JOIN SubPointList AS B ON A.ID = B.ID; /* 結果→全カラムがそのまま表示される +----+------+-------+----------+------+---------+----+------+-------+---------+---------------+ | ID | Name | Class | Japanese | Math | English | ID | Name | Class | Science | SocialStudies | +----+------+-------+----------+------+---------+----+------+-------+---------+---------------+ | 1 | 佐藤 | A | 100 | 100 | 85 | 1 | 佐藤 | A | 90 | 75 | | 2 | 鈴木 | A | 90 | 70 | 70 | 2 | 鈴木 | A | 90 | 70 | | 3 | 高橋 | A | 85 | 70 | 65 | 3 | 高橋 | A | 85 | 70 | | 4 | 中村 | A | 90 | 65 | 85 | 4 | 中村 | A | 40 | 0 | +----+------+-------+----------+------+---------+----+------+-------+---------+---------------+ */
システムエンジニアを目指したい方は
システムエンジニアを目指す方や、IT知識を1から身につけたい方は以下のページをご覧ください。
正直どこから学び始めればよいかわからない。どのように勉強していけば、エンジニアとしてのスキルが磨けるか?が分からない・・・という方は必見です。
システムエンジニア向けに「できるエンジニア」になる方法を1から解説しておりますので、是非ご覧ください。