SQLを用いたデータ操作において、複数のテーブルやクエリ結果を一つにまとめたい場面は頻繁に発生します。
例えば、年度ごとに分かれた売上テーブルを統合して集計したり、異なる部署の従業員リストを一括で取得したりする場合です。
このような「結果セットの統合」を実現するのがUNION(ユニオン)という演算子です。
本記事では、SQLのUNIONの基本的な概念から、実務で必ず直面するUNION ALLとの違い、さらには使用時に守るべき厳格なルールについて詳しく解説します。
これからSQLを本格的に学びたい方はもちろん、実務でのクエリ最適化を目指すエンジニアの方も、ぜひ参考にしてください。
SQL UNIONとは何か
SQLにおけるUNIONは、複数のSELECT文の結果を一つの結果セットとして垂直方向に結合するための集合演算子です。
データベースの操作において「結合」と聞くと、JOIN(外部結合や内部結合)を思い浮かべる方が多いかもしれません。
しかし、JOINが「横方向(列方向)」にテーブルをつなげるのに対し、UNIONは「縦方向(行方向)」にデータを積み上げるという決定的な違いがあります。
集合演算としてのUNION
数学の集合概念でいう「和集合」に相当するのがUNIONです。
2つのクエリ結果から重複する行を取り除き、すべてのデータを網羅した1つのリストを作成します。
例えば、Aというテーブルに「りんご、バナナ」があり、Bというテーブルに「バナナ、みかん」がある場合、UNIONを用いると結果は「りんご、バナナ、みかん」となります。
重複している「バナナ」は自動的に1つにまとめられるのが特徴です。
UNIONの基本構文と使い方
UNIONを使用する際の基本的な書き方は非常にシンプルです。
2つ(あるいはそれ以上)のSELECT文の間にUNIONというキーワードを挟むだけです。
基本的な書き方
-- 1つ目のクエリ
SELECT column1, column2 FROM table1
UNION
-- 2つ目のクエリ
SELECT column1, column2 FROM table2;
このように記述することで、table1から取得したデータとtable2から取得したデータが1つの表にまとまります。
具体的な使用例
例えば、東京支店の顧客リストと大阪支店の顧客リストを統合して、全社の顧客名簿を作成する場合を考えてみましょう。
-- 東京支店の顧客
SELECT customer_id, customer_name FROM tokyo_customers
UNION
-- 大阪支店の顧客
SELECT customer_id, customer_name FROM osaka_customers;
customer_id | customer_name
------------+--------------
T001 | 田中 太郎
T002 | 佐藤 花子
O001 | 鈴木 一郎
O002 | 高橋 次郎
このように、別々のテーブルに保管されている似た構造のデータを一括で扱いたい時に、UNIONは非常に強力なツールとなります。
UNIONを使用する際の4つの必須ルール
UNIONを使用するには、統合する複数のクエリ間で守らなければならない厳格なルールがいくつか存在します。
これらに違反すると、SQL実行時にエラーが発生します。
1. 列の数が一致していること
結合するすべてのSELECT文において、取得する列の数が同じでなければなりません。
例えば、1つ目のSELECT文で3つの列を指定し、2つ目で2つの列しか指定していない場合、SQLエンジンは「どのように積み上げればよいか」を判断できず、エラーを返します。
2. データ型に互換性があること
各列のデータ型は、対応する位置にある列同士で一致、または互換性がある必要があります。
1つ目のクエリの1番目の列が「数値型」であれば、2つ目のクエリの1番目の列も「数値型」である必要があります。
| 列の位置 | クエリ1のデータ型 | クエリ2のデータ型 | 判定 |
|---|---|---|---|
| 第1列 | INT | INT | OK |
| 第2列 | VARCHAR | VARCHAR | OK |
| 第3列 | DATETIME | INT | NG |
3. 列の順序が一致していること
列の数と型が合っていても、意味的に異なるデータが混ざらないよう注意が必要です。
SQLは列の名前ではなく「左から何番目か」でデータを統合します。
例えば、1つ目のクエリで「氏名、メールアドレス」の順、2つ目で「メールアドレス、氏名」の順に取得すると、結果セットの1列目に氏名とメールアドレスが混在してしまいます。
これは論理的なミスを招く原因となります。
4. カラム名は最初のSELECT文が優先される
結果セットとして表示されるカラム名は、一番最初に記述したSELECT文の見出しが採用されます。
2つ目以降のSELECT文でエイリアス(AS)を付けても、最終的な出力結果には反映されないことが多いため注意しましょう。
UNIONとUNION ALLの違い
UNIONを学ぶ上で最も重要なトピックが、UNIONとUNION ALLの使い分けです。
重複行の扱い
最大の違いは、重複するデータをどのように処理するかという点にあります。
UNION: 重複する行を削除し、一意な(ユニークな)行のみを返します。UNION ALL: 重複を削除せず、すべての行をそのまま返します。
パフォーマンスの違い
実務において非常に重要なのがパフォーマンスの観点です。
UNION(重複削除あり)は、内部的に「データを並べ替えて(ソート)、重複がないかチェックする」という処理を行います。
そのため、データ量が膨大になると処理時間が大幅に増加します。
一方で、UNION ALLは単純に結果を結合するだけなので、UNIONよりも圧倒的に高速に動作します。
どちらを使うべきか
基本的には、「重複がないことが最初からわかっている場合」や「重複していても問題ない場合」は UNION ALL を使用するのが鉄則です。
不必要にUNIONを使ってデータベースに負荷をかけることは避けましょう。
UNIONでのソート(ORDER BY)の活用方法
UNIONの結果全体を並べ替えたい場合、ORDER BY句の使用位置に注意が必要です。
最後に一度だけ記述する
ORDER BYは、個々のSELECT文に付けるのではなく、クエリの最後に一度だけ記述します。これにより、統合された後の最終的な結果セットに対してソートが実行されます。
SELECT product_name, price FROM products_a
UNION ALL
SELECT product_name, price FROM products_b
ORDER BY price DESC; -- 統合された後の全体を価格の降順で並べ替え
もし個別のSELECT文にORDER BYを記述しようとすると(サブクエリとして扱わない限り)、文法エラーになるのが一般的です。
実践的な活用シーン
UNIONは単なるテーブル結合以外にも、高度なレポート作成などで活用されます。
1. 売上データと目標データの統合
実績テーブルと予算目標テーブルを統合し、予実管理表のベースを作成する際によく使われます。
-- 実績データ
SELECT '実績' AS type, amount FROM sales_actual
UNION ALL
-- 目標データ
SELECT '目標' AS type, amount FROM sales_target;
このように、「どのテーブルから来たデータか」を識別するための固定文字列を列として追加するテクニックは実務で非常に重宝します。
2. 複数のテーブルに分散したログの調査
システム運用において、月ごとに分割されたログテーブル(logs_202401, logs_202402…)から特定のユーザーIDの挙動を一括で検索する場合などにUNION ALLが活躍します。
3. マスタデータの補完
あるテーブルに存在しないデータを、別のデフォルト値テーブルから補完してリスト化する場合などにも使用されます。
UNION使用時の注意点とトラブルシューティング
スムーズにUNIONを使いこなすために、初心者が陥りやすいポイントを確認しておきましょう。
NULL値の扱い
UNIONにおいて、すべての列がNULLである行が存在する場合、それも一つの値として評価されます。
もし2つのクエリの両方で「すべてNULL」の行が発生し、UNION(重複削除)を使用していれば、結果には1行だけNULL行が残ります。
異なるカラム名の統合
前述した通り、カラム名は1番目のSELECT文に依存します。
SELECT emp_id FROM employees
UNION
SELECT staff_no FROM contractors;
この場合、結果のヘッダーはemp_idになります。
もしわかりやすい名前にしたい場合は、最初のSELECT文でエイリアスを指定しましょう。
SELECT emp_id AS user_identifier FROM employees
UNION
SELECT staff_no FROM contractors;
パフォーマンス劣化への対策
数十万件、数百万件のデータをUNIONで統合する場合、一時メモリを大量に消費することがあります。
特にUNION(重複削除)を使用している場合は、インデックスが効かない処理になる可能性が高いため、WHERE句で事前にデータを絞り込んでから結合するなどの工夫が必要です。
-- 悪い例:全体を結合してから絞り込む
SELECT * FROM table_a UNION SELECT * FROM table_b WHERE date = '2026-05-01';
-- 良い例:各テーブルで絞り込んでから結合する
SELECT * FROM table_a WHERE date = '2026-05-01'
UNION ALL
SELECT * FROM table_b WHERE date = '2026-05-01';
まとめ
SQLのUNIONは、バラバラに管理されているデータを一つにまとめ、集合として扱うための非常に便利な機能です。
本記事の要点を振り返ります。
UNIONは「縦(行方向)」に結果を統合する。- 結合するためには「列数」「データ型」を一致させる必要がある。
- 重複を削除するなら
UNION、パフォーマンス重視ならUNION ALLを選択する。 - 並べ替え(
ORDER BY)は最後に一度だけ記述する。
特に実務においては、不必要な重複削除によるパフォーマンス低下を避けるため、UNION ALL を優先的に検討することが重要です。
これらのルールと特性を理解することで、より柔軟で効率的なデータ抽出が可能になります。
SQLの基礎をマスターし、データの統合・分析を自由自在に行えるよう、ぜひ今回紹介したクエリを自身の環境で試してみてください。
