【SQL】UNIONを使って複数の検索結果を統合!初心者向けに解説

複数のSELECT文の結果を統合するためにはUNIONを使います。

本記事では、UNIONとは何か、UNIONの基本的な使い方、ORDER BY句やGROUP BY句との併用方法まで具体例を交えながら解説します。

UNIONとは何か

UNIONを使うことで、2つ以上のSELECT文の結果を統合することができます。

下記のようにSELECT文で得た結果が2つあった場合、UNIONを使うことで一つの結果に統合できます。

UNIONとUNION ALLの違い

UNIONには「UNION」と「UNION ALL」の2つの種類があります。

UNION・・・統合結果から重複レコードは削除する
UNION ALL・・・統合結果に重複レコードも含める

具体例を見てみましょう。

UNIONの場合

下記のようにusersテーブルとemployeeテーブルの取得結果を統合してみます。usersテーブルにもemployeeテーブルにも「id1name山田」のレコードが存在します。

UNIONの場合は重複レコードは除外するため、統合結果から「id1name山田」のレコードは除外されます。

UNION ALLの場合

一方で、UNION ALLの場合は、重複したレコードであっても全て取得するため、統合結果にも2つの「id1name山田」のレコードが存在しています。

UNIONの使いどころ

同じような情報を扱っているテーブルが複数存在していて、一箇所に一覧化したい時に使います。

エクセルを例に取ると、イベントAの申込者情報とイベントBの申込者情報を別のエクセルで管理していたとします。これらを別々ではなく一箇所にまとめたい場合、同じ列同士に絞って統合するのではないでしょうか。

これと同じことをUNIONを使って実現しているイメージです。

サンプルデータ

下記のとおり、会員情報を管理するmembersテーブルと、とあるイベントの申込者を管理するevent_usersテーブルを用意します。

idnameemail
1山田yamada@gmail.com
2鈴木suzuki@gmail.com
3佐藤sato@gmail.com
4佐々木sasaki@gmail.com
membersテーブル
idnameemail
1今野konno@gmail.com
2鈴木suzuki@gmail.com
3佐藤s.sato@gmail.com
event_usersテーブル

UNIONの使い方

UNIONの場合

UNIONの基本構文は下記です。

SQL
SELECT カラム名 FROM テーブル名1
UNION
SELECT カラム名 FROM テーブル名2;

1つ目と2つ目それぞれのSELECT句で指定するカラムは同じである必要があります。

検索クエリ

SQL
SELECT *
FROM members
UNION
SELECT *
FROM event_users;

1つ目のSELECT文SELECT * FROM membersと2つ目のSELECT文SELECT * FROM event_usersの間にUNIONを置いて2つのSELECT文を統合しています。

実行結果

idnameemail
1山田yamada@gmail.com
2鈴木suzuki@gmail.com
3佐藤sato@gmail.com
4佐々木sasaki@gmail.com
1今野konno@gmail.com
3佐藤s.sato@gmail.com

membersテーブルとevent_usersテーブルを統合できました。event_usersテーブルにあった「id:2、name:鈴木、email:suzuki@gmail.com」のレコードはusersテーブルにも存在するため、重複として除外されています。

id:3name:佐藤」のレコードは2つありますが、emailの値が異なるため、重複とはみなされず2つとも取得しています。

UNION ALLの場合

UNION ALLの基本構文は下記です。UNIONと書き方は同じですね。

SQL
SELECT カラム名 FROM テーブル名1
UNION ALL
SELECT カラム名 FROM テーブル名2;

UNIONと同様に、1つ目と2つ目それぞれのSELECT句で指定するカラムは同じである必要があります。

検索クエリ

SQL
SELECT *
FROM members
UNION ALL
SELECT *
FROM event_users;

2つのSELECT文の間にUNION ALLを指定しています。

実行結果

idnameemail
1山田yamada@gmail.com
2鈴木suzuki@gmail.com
3佐藤sato@gmail.com
4佐々木sasaki@gmail.com
1今野konno@gmail.com
2鈴木suzuki@gmail.com
3佐藤s.sato@gmail.com

UNIONの時はevent_usersテーブルのid2のレコードは除外されていましたが、UNION ALLでは重複も含むため取得しています。

UNIONを使った後にORDER BY句で並べ替え

UNIONを使って検索結果を統合した後に並べ替えを行うことができます。

並べ替えにはORDER BY句を使います。

SQL
SELECT カラム名 FROM テーブル名1
UNION 
SELECT カラム名 FROM テーブル名2
ORDER BY カラム名 [ASC, DESC];

では、具体例を見ていきましょう。

検索クエリ

membersテーブルとevent_usersテーブルの検索結果を統合した上で、idが最新順にレコードを並べる

SQL
SELECT *
FROM members
UNION ALL
SELECT *
FROM event_users
ORDER BY id DESC;

最後にORDER BY id DESCで昇順に並べ替えています。

実行結果

idnameemail
4佐々木sasaki@gmail.com
3佐藤sato@gmail.com
3佐藤s.sato@gmail.com
2鈴木suzuki@gmail.com
2鈴木suzuki@gmail.com
1山田yamada@gmail.com
1今野konno@gmail.com

idを昇順に並べ替えてデータを取得することができました。

ORDER BY句については下記にまとめています。

【SQL】ORDER BY句を使ってレコードを並び替える方法(降順・昇順でソート)

UNIONを使った後にGROUP BY句でグループ化

次に、UNIONを使って検索結果を統合した後にGROUP BY句を使ってグループ化する方法を見ていきます。

UNIONで統合したデータにそのままGROUP BY句を使うことができないため、FROM句に副問合せを使って副問合せの中で検索結果を統合します。

検索クエリ

membersテーブルとevent_usersテーブルの検索結果を統合した上で、email情報でデータをグループ化する

SQL
SELECT *
FROM (
  SELECT *
  FROM members
  UNION ALL
  SELECT *
  FROM event_users
) users
GROUP BY id, name, email;

下記の流れで考えます。

  1. FROM句の後に()をつけて副問合せを使う
  2. 副問合せの中でUNION ALLを使ってSELECT文を2つ統合する
  3. 副問合せの閉じカッコの後にテーブル名を付ける
  4. 最後にGROUP BYを使ってid, name, emailを指定してグループ化する(SELECT句で全てのカラムを指定しているため、GROUP BY句でも全てのカラムを指定する必要がある)

実行結果

idnameemail
1今野konno@gmail.com
1山田yamada@gmail.com
2鈴木suzuki@gmail.com
3佐藤s.sato@gmail.com
3佐藤sato@gmail.com
4佐々木sasaki@gmail.com

id, name, emailの全ての値が一致した場合にグループ化されます。よって、今回の場合はidが2レコードのみグループ化されました。

GROUP BY句については下記にまとめています。

GROUP BY句を使って集計!COUNTやHAVINGとの合わせ技も解説【SQL】

副問合せ(サブクエリ)については下記にまとめています。

【SQL】副問合せ(サブクエリ)の使い方を初心者向けに解説

内容のまとめ

  • UNIONを使うことで、2つ以上のSELECT文の結果を統合できる
  • UNIONには「UNION」と「UNION ALL」の2種類があり、UNIONは統合結果から重複レコードを除外し、UNION ALLは統合結果に重複レコードも含める
  • UNIONは同じような情報を扱っているテーブルが複数存在していて、一箇所に一覧化したい時に使う
  • UNIONの基本構文は、SELECT カラム名 FROM テーブル名1 UNION SELECT カラム名 FROM テーブル名2;
  • UNIONを使った後にレコードを並べ替える場合は、ORDER BY句を使う
  • UNIONを使った後にグループ化する場合はGROUP BY句を使うが、統合結果に直接GROUP BYは使えない。そのため、FROM句に副問合せを使って副問合せの中で検索結果を統合する