SQLにおける UNION/UNION ALL の使い方をデータベース初心者向けにわかりやすく3分で解説します。
UNION/UNION ALL はどちらもSELECT文で抽出した結果を統合する際に利用します。
このページでは初めてSQLを利用する方でも理解できるようにすべて図解付き・サンプルコード付きでご説明します。
プログラマーやデータベースエンジニアを目指す方であれば知らないと恥ずかしい超・基本知識。是非最後までご覧ください。
SQL文の基本ルール(大文字/小文字の区別、コメントの付与など)を始めに学んでおきたい方は以下の記事を先にご覧ください。
SQL:UNION
まずは、UNIONの使い方から解説します。
後ほど解説しますが、UNIONとUNION ALLの違いは以下の通り。
SQL文のルール自体はほぼ同じなので、まずは基本的なUNIONの書き方から丁寧に学習していきましょう。
SELECT カラム名 FROM テーブル名1 UNION SELECT カラム名 FROM テーブル名2
文法自体は非常に簡単でSELECT文をUNIONで繋げるだけ。早速、実際にUNIONを利用したSQL文を実行していきましょう。
ここでは、以下のような2つのテーブルを利用します。
参考までに上記のMemberList_A/MemberList_Bテーブルを用意するためのCREATE TABLE文/INSERT文を掲載しておきます。
CREATE TABLE MemberList_A ( Number INT(2), Name VARCHAR(50), Class VARCHAR(1) ); /*MemberList_A定義 +--------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+-------------+------+-----+---------+-------+ | Number | int(2) | YES | | NULL | | | Name | varchar(50) | YES | | NULL | | | Class | varchar(1) | YES | | NULL | | +--------+-------------+------+-----+---------+-------+ */ CREATE TABLE MemberList_B ( Number INT(2), Name VARCHAR(50), Class VARCHAR(1) ); /*MemberList_B定義 +--------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+-------------+------+-----+---------+-------+ | Number | int(2) | YES | | NULL | | | Name | varchar(50) | YES | | NULL | | | Class | varchar(1) | YES | | NULL | | +--------+-------------+------+-----+---------+-------+ */ -- INSERT INSERT INTO MemberList_A (Number,Name,Class) VALUES (1,'イチロウ','A'); INSERT INTO MemberList_A (Number,Name,Class) VALUES (2,'ジロウ','A'); INSERT INTO MemberList_A (Number,Name,Class) VALUES (3,'サブロウ','A'); INSERT INTO MemberList_A (Number,Name,Class) VALUES (4,'シロウ','A'); INSERT INTO MemberList_B (Number,Name,Class) VALUES (1,'イチロウ','B'); INSERT INTO MemberList_B (Number,Name,Class) VALUES (2,'ジロウ','B'); INSERT INTO MemberList_B (Number,Name,Class) VALUES (3,'ゴロウ','B'); INSERT INTO MemberList_B (Number,Name,Class) VALUES (4,'ハチロウ','B');
この2つのテーブルから取得した結果を1つの結果として表示します。
-- UNION SELECT Number,Name,Class FROM MemberList_A UNION SELECT Number,Name,Class FROM MemberList_B; /* 結果 +--------+----------+-------+ | Number | Name | Class | +--------+----------+-------+ | 1 | イチロウ | A | | 2 | ジロウ | A | | 3 | サブロウ | A | | 4 | シロウ | A | | 1 | イチロウ | B | | 2 | ジロウ | B | | 3 | ゴロウ | B | | 4 | ハチロウ | B | +--------+----------+-------+ */
2つのSELECT文の結果を1つのまとめて(統合して)取得することができました。
この2つのテーブルはカラム数やデータ型が完全に一致しているので、以下のようにワイルドカードを利用しても問題ありません。
-- UNION SELECT * FROM MemberList_A UNION SELECT * FROM MemberList_B; /* 結果 +--------+----------+-------+ | Number | Name | Class | +--------+----------+-------+ | 1 | イチロウ | A | | 2 | ジロウ | A | | 3 | サブロウ | A | | 4 | シロウ | A | | 1 | イチロウ | B | | 2 | ジロウ | B | | 3 | ゴロウ | B | | 4 | ハチロウ | B | +--------+----------+-------+ */
また、カラムはテーブルのすべての列を指定する必要もないので、必要なカラムだけを指定することも可能です。
-- UNION SELECT Name,Class FROM MemberList_A UNION SELECT Name,Class FROM MemberList_B; /* 結果 +----------+-------+ | Name | Class | +----------+-------+ | イチロウ | A | | ジロウ | A | | サブロウ | A | | シロウ | A | | イチロウ | B | | ジロウ | B | | ゴロウ | B | | ハチロウ | B | +----------+-------+ */
SQL:UNION ALL
続いてUNION ALLについて解説します。UNIONとUNION ALLの違いは以下の通り。
例えば、UNIONの場合は2つのSELECT文の結果に重複がある場合、以下のように重複行が除かれます。
-- SQL文 SELECT Number,Name FROM MemberList_A UNION SELECT Number,Name FROM MemberList_B; /* 結果→重複行が除外 +--------+----------+ | Number | Name | +--------+----------+ | 1 | イチロウ | | 2 | ジロウ | | 3 | サブロウ | | 4 | シロウ | | 3 | ゴロウ | | 4 | ハチロウ | +--------+----------+ */
2つのSELECT文の結果の両方に含まれるNumber1~2のレコードが除外されて統合されています。
一方でUNION ALLを利用すれば重複している行が除外されずに出力されます。
-- SQL文(UNION ALL) SELECT Number,Name FROM MemberList_A UNION ALL SELECT Number,Name FROM MemberList_B; /* 結果→重複行は除外されない +--------+----------+ | Number | Name | +--------+----------+ | 1 | イチロウ | | 2 | ジロウ | | 3 | サブロウ | | 4 | シロウ | | 1 | イチロウ | | 2 | ジロウ | | 3 | ゴロウ | | 4 | ハチロウ | +--------+----------+ */
UNION ALLとUNIONの使い分けは簡単なのですが、プログラムを実装していく上では誤りが出やすいポイントでもあります。
よく注意して覚えておきましょう!
UNION/UNION ALLの注意点
文法上はどちらも非常に簡単なのですが、注意点が3点存在します。
最後にこの3つの注意点を解説します。
UNION―注意点1:指定するカラムの数は同じにすること
UNION/UNION ALLでは、指定するカラムの数が必ず一致している必要があります。
例えば、以下のSQLは2つのSELECT文で指定しているレコード数が異なるためエラーが発生します。
-- エラーが発生するパターン1 SELECT Number,Name,Class FROM MemberList_A UNION SELECT Number,Name FROM MemberList_B; --ERROR 1222 (21000): The used SELECT statements have a different number of columns
逆に言えば、指定するカラムの数が一致していれば以下のようなSQLは正常に動作します。
SELECT Number,Name FROM MemberList_A UNION SELECT Number,Class FROM MemberLIst_B; /* 結果 +--------+----------+ | Number | Name | +--------+----------+ | 1 | イチロウ | | 2 | ジロウ | | 3 | サブロウ | | 4 | シロウ | | 1 | B | | 2 | B | | 3 | B | | 4 | B | +--------+----------+ */
1つ目のSQL文で指定したカラム名に沿う形で結果が統合されていることが分かります。
UNION―注意点2:指定するカラムのデータ型が一致していること
注意点の2つ目が「データ型」です。指定するカラム(=左から数えて同じ位置にあるカラム)のデータ型は一致している必要があります。
例えば、以下のようなSQLはエラーになります。
SELECT Number FROM MemberList_A UNION SELECT Class FROM MemberLIst_B; /* Number →INT型 Class →Varchar型 */
UNION―注意点3:ORDER BY句は最後に1つだけ利用すること
UNIONを利用するSQL文では、ORDER BY句は全体の最後に一度だけしか利用できないという注意点があります。
例えば、以下のSQL文では、ORDER BY句をそれぞれのSELECT文の中で利用しているためエラーが発生します。
SELECT Number,Name FROM MemberList_A ORDER BY Number UNION ALL SELECT Number,Name FROM MemberList_B ORDER BY Number; -- ERROR 1221 (HY000): Incorrect usage of UNION and ORDER BY
正しい文法では、以下のように全体の最後に1度だけ利用します。
SELECT Number,Name FROM MemberList_A UNION ALL SELECT Number,Name FROM MemberList_B ORDER BY Number; /* 正常に結果が取得できる +--------+----------+ | Number | Name | +--------+----------+ | 1 | イチロウ | | 1 | イチロウ | | 2 | ジロウ | | 2 | ジロウ | | 3 | サブロウ | | 3 | ゴロウ | | 4 | ハチロウ | | 4 | シロウ | +--------+----------+ */
システムエンジニアを目指したい方は
システムエンジニアを目指す方や、IT知識を1から身につけたい方は以下のページをご覧ください。
正直どこから学び始めればよいかわからない。どのように勉強していけば、エンジニアとしてのスキルが磨けるか?が分からない・・・という方は必見です。
システムエンジニア向けに「できるエンジニア」になる方法を1から解説しておりますので、是非ご覧ください。