【Oracle】UNIONとUNION ALLの違いを解説

【Oracle】UNIONとUNION ALLの違いを解説

記事の文字数:2496

Oracleデータベースを学ぶ際に混乱しやすいのが「UNION」と「UNION ALL」の違いです。どちらも複数のSELECT文を結合して結果をまとめるために使いますが、重複行の扱いやパフォーマンスに大きな差があります。本記事では、それぞれの特徴や具体的な使い分け、実際のSQL例を交えてわかりやすく解説します。

UNION UNION ALL 違いというキーワードで検索する人は主に以下を知りたいはずです。

  • 2つの演算子がどのように結果を変えるか(重複の扱い)
  • パフォーマンスにどれくらい差があるか
  • 実務でどちらを使うべきか

本記事では上記の疑問に対して、Oracleを例に違い→実例→実践的な使い分けまでを網羅的に解説します。

UNIONとUNION ALLの違い

  • UNION:複数のSELECTの結果を結合し、重複行を取り除く(内部的にはDISTINCT相当の処理が行われる)。
  • UNION ALL:複数のSELECTの結果をそのまま連結する。重複は排除されない。

一言で言えば重複を取り除くかどうかが主な違いで、UNIONは重複を取り除きUNION ALLは重複を取り除きません。

UNIONとUNION ALLの違いを実例から確認

サンプルデータの準備(例)

CREATE TABLE emp_a (id NUMBER, name VARCHAR2(20));
CREATE TABLE emp_b (id NUMBER, name VARCHAR2(20));
INSERT INTO emp_a VALUES (1, '佐藤');
INSERT INTO emp_a VALUES (2, '鈴木');
INSERT INTO emp_a VALUES (4, NULL);
INSERT INTO emp_b VALUES (2, '鈴木');
INSERT INTO emp_b VALUES (3, '高橋');
INSERT INTO emp_b VALUES (4, NULL);
COMMIT;

UNION の例

SELECT id, name FROM emp_a
UNION
SELECT id, name FROM emp_b;

結果(説明)

  • (1, 佐藤)
  • (2, 鈴木) — emp_a と emp_b にある重複が1行にまとめられる
  • (3, 高橋)
  • (4, NULL) — NULLも1行にまとめられる

UNION ALL の例

SELECT id, name FROM emp_a
UNION ALL
SELECT id, name FROM emp_b;

結果(説明)

  • (1, 佐藤)
  • (2, 鈴木) — emp_a の行
  • (4, NULL) — emp_a の行
  • (2, 鈴木) — emp_b の行(重複がそのまま残る)
  • (3, 高橋)
  • (4, NULL) — emp_b の行(重複がそのまま残る)

UNIONとUNION ALLのパフォーマンスの違い

  • UNION は重複排除のための追加処理(ソートかハッシュ集約)を行うので、計算コストが高くなりがちです。データ量が増えるほど、差は大きくなります。
  • UNION ALL は単純に結果を連結するだけなので、基本的に高速です。

Oracleの実行計画では、UNIONを使うとSORT UNIQUEHASH UNIQUEのような演算子が登場することがあり、これがコスト増の主因になります。

結論(パフォーマンス面):重複の可能性がない(あるいは重複を気にしない)場合はUNION ALLを選ぶべきです。不要なUNIONの使用は避ける。

UNIONとUNION ALLの構文上のルールと注意点

結合時のカラム数と型の互換性

  • 結合するすべてのSELECT同じ数の列を返す必要があります。
  • 同じ順序で、互換性のあるデータ型でなければなりません(暗黙の型変換が働く場合もありますが、安全のため明示的にキャストすることが推奨されます)。

列名は先頭のSELECTから決まる

  • 結果セットの列名(ヘッダ)は、最初のSELECT句の列名が使われます。

ORDER BYは最終結果に適用

  • ORDER BY最終結果に対して適用されます。各サブSELECTORDER BYを書いても、最終結果の並びは保証されません。

UNION時のNULLの扱い

UNION(重複排除)の際、NULLは等価とみなされるため、複数の列値がすべてNULLの行は重複として扱われ、1行にまとめられます。

例:

  • SELECT NULL, 1 FROM ... が複数行ある場合、UNIONでは1行にまとめられます。

ORDER BY・列名・型の扱い(補足)

  • ORDER BY全体に対して効くため、個々のサブクエリの並びを期待するのは間違いです。サブクエリにORDER BYを書いても最終結果の保証にはならないので注意してください。
  • 列のデータ型が微妙に異なる場合、Oracleは暗黙的に変換しますが、想定外の変換や精度損失が起こることがあります。安全のためCASTで合わせたほうがベターです。

UNIONとUNIONALLのよくある誤解

  • 誤解UNIONは単にUNION ALLの別名である。 → 訂正UNIONは重複を排除するために追加処理が走る。
  • 誤解:NULLは重複判定で常に異なると扱われる。 → 訂正UNIONの重複判定ではNULLは等価とみなされる(同じNULL同士は重複としてまとめられる)。

UNIONとUNION ALLの使い分け

重複が論理的にあり得ない(別ソースのIDが被らない)

UNION ALL を使う。余計なオーバーヘッドを避けられます。

重複を必ず排除したい(名寄せのような場合)

UNION または UNION ALL + 明示的な重複排除(ROW_NUMBER()で一意を決める)

集計を取りたい(重複をまとめて集計する)

  • UNION ALLで連結後にGROUP BYする方がパフォーマンスが良いケースがあります(特に各ソースの行数が大きく、並列処理が効く場合)。

UNION・UNION ALLまとめ

  • 重複を排除したいなら:UNION(ただしパフォーマンスコストあり)。
  • 重複を許容する、または重複が発生しないと確信できるなら:UNION ALL(高速)。
  • 結合するSELECTは列数・型を合わせる

UNION・UNION ALLのFAQ

Q1. UNIONDISTINCT の違いは? A: 機能的には同じ(重複排除)。UNIONは複数のSELECTを結合して結果全体で重複を排除する操作です。SELECT ... DISTINCTは単一のSELECTの結果に対して重複排除を行います。

Q2. どちらが速いですか? A: 一般にUNION ALL。ただし実際の速度はデータ量、インデックス、統計、実行計画に依存します。


以上で本記事の解説を終わります。
よいITライフを!
Scroll to Top