SQL UNION ALLの使い方と活用ガイド: UNIONとの違いを徹底解説
CONTENTS
SQLにおいて複数のSELECT文の結果を一つの結果セットにまとめる方法の中でも、UNIONとUNION ALLは重要なセット演算子です。本記事では、両者の構文や違い、実践例を紹介しながら使い分けを解説します。
さらに、JOINとの比較や注意点、実務での活用例などを取り上げ、SQLをより効率的に活用するためのベストプラクティスをご紹介します。
初心者の方でも理解しやすいように基礎的な部分から押さえつつ、実際の業務を想定した深い観点から考察していきます。
SQLのセット演算子とは?基本概念と目的
まずはSQLのセット演算子の概要と、なぜ複数の結果セットをまとめる必要があるのかを理解しましょう。
SQLのセット演算子は複数のクエリ結果を一つにまとめる機能を提供します。同じ列構成のSELECT文を組み合わせることで、テーブルを横断した集計や分析が容易になります。例えばテーブルAとテーブルBの抽出結果をまとめて扱う場合、手作業で集計するよりはるかに効率的です。
データベースを活用する場面では、部署ごとに分割されたデータや異なる条件で抽出したデータを一度に統合したいケースがよくあります。セット演算子を使うことで、必要な行をひとまとめにして処理でき、後の分析やレポート作成がスムーズに行えます。
また、JOINと異なり、テーブル間の関連付けではなく結果セット同士を縦に連結するため、データが重複している場合や統合後にフィルタリングを行う場合などに非常に役立ちます。こうした場面で特に使用されるのがUNIONやUNION ALLです。
| 項目 | 説明 |
|---|---|
| セット演算子の役割 | 複数のクエリ結果を一つにまとめる |
| 主な利点 | テーブル横断の集計・分析が容易になる |
| JOINとの違い | 横方向の結合ではなく、縦方向の連結を行う |
| 適用シーン | 部署別データの統合、異なる条件での抽出結果の統合 |
ポイント: セット演算子は「結果セット同士を縦に連結」する点がJOINとの最大の違いです。テーブル間の関係性ではなく、抽出結果そのものを束ねる用途で使用します。
UNIONとUNION ALLの基本構文
UNIONとUNION ALLを使う際に必要となる基本構文を確認し、主要なポイントを押さえましょう。
UNIONとUNION ALLはどちらも構文自体はシンプルで、SELECT文の結果セットの間に演算子を挟むだけで利用できます。ただし、複数のSELECT文の列数やデータ型は一致している必要があります。それを満たさないとエラーになったり、想定外の結果が得られる可能性があります。
特に文字型と数値型といった合わないデータ型を無理に結合すると、その列だけは文字型に変換される場合もあります。これによって意図しないデータ型変換が発生し、パフォーマンスが低下する恐れもあるため注意が必要です。
基本的に、UNIONやUNION ALLでまとめる候補のSELECT文は、同じ意味合いの列を同じ順番で並べるよう作成することが望ましいです。これによって後から読み解きやすくなり、他の開発者や運用担当者との情報共有もしやすくなります。
基本構文の例
-- UNION の基本構文
SELECT column1, column2 FROM table1
UNION
SELECT column1, column2 FROM table2;
-- UNION ALL の基本構文
SELECT column1, column2 FROM table1
UNION ALL
SELECT column1, column2 FROM table2;
注意事項
- 列数が一致していないとエラーが発生します
- データ型の不一致は自動変換されることがありますが、パフォーマンス低下の原因になります
- 列の順序も同じにする必要があります
UNIONの特徴と書き方
UNIONは複数の結果セットを結合し、重複する行を自動的に取り除きます。これにより、重複のないユニークな集合が得られるため、特定のディメンションごとに集計する際などに便利です。一方で、重複除去の工程にはコストがかかるため、パフォーマンス面では注意が必要です。
基本的な書き方は、SELECT文同士をUNIONでつなぐだけです。列名やデータ型は上部のSELECT文に合わせられるので、複数のSELECTで一致するかを必ず確認しましょう。列数が揃っていないとエラーになる点も押さえておきましょう。
例えば、従業員テーブルと管理職テーブルがあった場合、共通のカラム構造を持つSELECT文をUNIONでつなげば、重複を排除した管理職を含む従業員リストを取得できます。
以下は本文を整理した実装例です
-- 従業員と管理職を統合し、重複を排除する例
SELECT employee_id, name, department FROM employees
UNION
SELECT manager_id, name, department FROM managers;
UNIONの主な特徴
| 特徴 | 詳細 |
|---|---|
| 重複処理 | 自動的に重複行を削除 |
| パフォーマンス | 重複チェックのコストがかかる |
| 用途 | ユニークなデータセットが必要な場合 |
| 結果 | 一意な行のみ返される |
UNION ALLの特徴と書き方
UNION ALLは重複行をそのまま残して結果を結合するため、UNIONに比べてより多くの行が返される可能性があります。データを完全に取り込んで分析したい場合や、後から重複判定を自前で行いたい場合に適しています。
また、UNION ALLは重複を排除する処理を行わないため、UNIONよりもパフォーマンスが高いことが多いです。大規模データの集計などでは、重複行が多くない場合はUNION ALLを選ぶことで処理時間短縮につながるケースがあります。
実際のSQL文は、UNIONとほぼ同じ書き方ですが、結合部分のキーワードをUNION ALLに変更するだけです。最終的な目的に応じて、重複が問題となるかどうかを判断して使い分けましょう。
以下は本文を補足するコード例です
-- すべての行を保持したまま結合する例
SELECT product_id, sales_amount, region FROM sales_2024
UNION ALL
SELECT product_id, sales_amount, region FROM sales_2025;
UNION・UNION ALLの実践例
実際にWHERE句やORDER BY句などと組み合わせて利用するケースや、サブクエリに組み込んで活用する方法を紹介します。
UNIONやUNION ALLは単純に結果セットを結合するだけでなく、追加の条件をかけたり並び替えを行うなど、他のSQL文の構文と組み合わせて応用できます。多彩な要件に柔軟に対応するための工夫点を見ていきましょう。
特に集計や分析を行う際には、WHERE句で対象データを絞り込んだ上でUNIONやUNION ALLを使う方法が有効です。また、最終的な結果セットに対してORDER BYを使えば、見やすい形式で結果を確認できます。
実務では複数のテーブルや条件を組み合わせる状況が頻繁に生じるため、こうした応用パターンを覚えておくことで、更なるSQLの活用幅が広がります。
WHERE句・ORDER BY句との組み合わせ
WHERE句は各SELECT文の抽出範囲を指定するため、不要な行を事前に除外する役割を果たします。特に、多様な条件で抽出したデータをUNIONでまとめたい場合に有効です。
ORDER BY句は結合後の結果セット全体に対して一度だけ指定するのが原則です。各SELECT文ごとにORDER BYを付けるとエラーになったり、期待通りの順番でソートされないことがあるため注意しましょう。
例えば、必要な行だけを絞り込んだSELECTをUNION ALLで結合し、最後にORDER BYを適用する、という手順をとることで効率的に並び替えができ、必要な情報を整理して得ることが可能になります。
以下は本文で説明した内容の実装例です
-- WHERE句とORDER BY句を組み合わせた例
SELECT order_id, customer_name, order_date
FROM orders_2024
WHERE order_date >= '2024-01-01'
UNION ALL
SELECT order_id, customer_name, order_date
FROM orders_2025
WHERE order_date >= '2025-01-01'
ORDER BY order_date DESC;
重要な注意点: ORDER BY句は最後に1回だけ記述します。各SELECT文に個別にORDER BYを付けるとエラーの原因になります。
サブクエリでの利用
UNIONやUNION ALLはサブクエリとして利用することもでき、より複雑なクエリを構築する際に便利です。例えば、結合結果を一時的にまとめてから、その中で追加のグループ化やソートを行うことが可能になります。
複雑なロジックを複数のSELECTで書き分けてから、UNION ALLでまとめ、外側のSELECTで最終的な集計や条件分岐を施すパターンは、多くの業務で活用されています。
ただし、サブクエリを多用すると可読性が下がる場合もあるため、必要に応じてビューを作成するなど、適切なSQL設計を心がけることが重要です。
以下は本文を補足するサブクエリの実装例です
-- サブクエリとしてUNION ALLを使用する例
SELECT department, COUNT(*) as total_count
FROM (
SELECT department FROM employees
UNION ALL
SELECT department FROM contractors
) AS all_staff
GROUP BY department
ORDER BY total_count DESC;
-- さらに複雑な集計を行う例
SELECT
status,
AVG(amount) as avg_amount,
SUM(amount) as total_amount
FROM (
SELECT 'completed' as status, amount FROM sales_2024 WHERE status = 'completed'
UNION ALL
SELECT 'completed' as status, amount FROM sales_2025 WHERE status = 'completed'
) AS completed_sales
GROUP BY status;
JOINとの比較:セット演算かデータ結合か
テーブル間の行を結合するJOINと、結果セットを束ねるUNION系演算子は用途が異なります。両者の役割を正しく理解しましょう。
JOINはテーブル間の共通キーを基にして横方向に行を結合します。一方、UNIONやUNION ALLは縦方向に結果セットを連結するための手段です。目的やデータ構造によって使い分けが必要となります。
JOINが必要となるケースは、関連する情報を一つのテーブルにまとめて表示したいときです。一方で、複数のSELECT文の結果を単純にまとめたいだけであれば、UNIONやUNION ALLが向いています。
両者を混同すると、想定外のデータが返ってきたり、不要に冗長なクエリを書いてしまう恐れがあります。目的を明確にし、最適なアプローチを選びましょう。
上記内容を整理した比較表
| 比較項目 | JOIN | UNION / UNION ALL |
|---|---|---|
| 結合方向 | 横方向(列を追加) | 縦方向(行を追加) |
| 基準 | 共通キー(関係性) | 列構造の一致 |
| 目的 | 関連データの統合表示 | 複数クエリ結果の統合 |
| 典型例 | 顧客と注文の結合 | 複数年度のデータ統合 |
| 出力 | 列数が増加 | 行数が増加 |
使い分けの具体例
-- JOIN の例:横方向の結合
SELECT o.order_id, o.order_date, c.customer_name
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id;
-- UNION の例:縦方向の連結
SELECT order_id, order_date, 'domestic' as market FROM domestic_orders
UNION ALL
SELECT order_id, order_date, 'international' as market FROM international_orders;
選択のポイント: 「関連するテーブルの情報を横に並べたい」→ JOIN、「同じ構造の複数データを縦に積み上げたい」→ UNION/UNION ALL
UNION・UNION ALLで注意したいポイント
UNIONやUNION ALLを利用する際に気をつけたい、列数やデータ型、ORDER BY句の使い方について解説します。
複数のSELECT文をつなぐ場合、それぞれのカラム数とデータ型が一致している必要があります。列数やデータ型が合わないとエラーになるだけでなく、意図しないデータ型変換が発生することもあるので注意しましょう。
ORDER BY句は、結合後の結果セットに対して一度だけ指定できます。複数のSELECT文それぞれにORDER BYを指定すると、実行エラーや非効率な処理が行われる可能性もあるため、最終的な結果セットに絞ってソートを行うのが基本です。
さらに、重複行が必要かどうか、どの程度のパフォーマンスが求められるかによってUNIONとUNION ALLを使い分けると、意図通りの結果を得られ、かつ効率的なクエリを実現できます。
カラム数とデータ型を揃える
UNIONやUNION ALLでは、結合するSELECT文間で列数が異なると実行エラーになります。対応する列同士が同じデータ型であるかも重要で、型が異なるとデータベースによっては自動変換が行われる場合があります。
例えば、文字型と数値型を結合させると文字型に統一されることが多く、ソートや集計に支障が出ることがあります。可能な限り同一の型に合わせておくのがベストプラクティスです。
また、可読性を高めるためにも、SELECT句で同じ列順序と列名を指定することが望ましいです。結果セットの内容が分かりやすくなり、メンテナンス性も向上します。
よくあるエラーと対処法(本文内容を補足)
-- ❌ エラー例:列数が一致しない
SELECT id, name FROM users
UNION
SELECT id, name, email FROM customers; -- 列数が異なるためエラー
-- ✅ 正しい例:列数を揃える
SELECT id, name, NULL as email FROM users
UNION
SELECT id, name, email FROM customers;
-- ❌ エラー例:データ型の不一致
SELECT id, name FROM users -- id: INTEGER
UNION
SELECT name, id FROM customers; -- 1列目が VARCHAR
-- ✅ 正しい例:列の順序とデータ型を揃える
SELECT id, name FROM users
UNION
SELECT id, name FROM customers;
チェックリスト
- すべてのSELECT文で列数が同じか
- 対応する列のデータ型が一致しているか
- 列の順序が揃っているか
- 列名が分かりやすいか(AS句で明示)
ORDER BY句は最後に1つだけ
SQLのセット演算子を使う場合、SELECT文ごとにORDER BYを指定することは基本的に想定されていません。全てのSELECTをUNIONまたはUNION ALLで連結した後に、1回だけORDER BY句を使うべきです。
もし複数回ORDER BYを記述すると、実行エラーや意図しないソート結果を生む可能性があります。必要なソートがある場合は、最終的に得られる結果セットで一括して並び替えるようにしましょう。
こうした書き方をうまく活用すると、効率的に処理が行われると同時に、クエリの可読性も維持しやすくなります。
正しいORDER BYの使い方(本文を補足する例)
-- ❌ 誤った例:各SELECT文にORDER BYを付ける
SELECT id, name FROM users ORDER BY name
UNION ALL
SELECT id, name FROM customers ORDER BY name; -- エラーになる可能性あり
-- ✅ 正しい例:最後に1回だけORDER BYを指定
SELECT id, name FROM users
UNION ALL
SELECT id, name FROM customers
ORDER BY name;
-- ✅ 複数列でのソートも可能
SELECT id, name, created_at FROM users
UNION ALL
SELECT id, name, created_at FROM customers
ORDER BY created_at DESC, name ASC;
重要: ORDER BY句は結合後の結果セット全体に対して適用されるため、必ず最後に1回だけ記述してください。
実務での活用例とベストプラクティス
例えば大規模なレポーティングや集計業務など、実務でよく見られるケースにおいての活用例とポイントを紹介します。
大規模プロジェクトでは、データが複数のテーブルや異なる期間に分割されて蓄積されるケースが多くあります。これを年ごとまたは月ごとにSELECT文で抽出し、UNION ALLでまとめると、一度に分析対象のすべてを扱うレポートを作成しやすくなります。
また、重複するデータを統合前に精査する必要がある場面も存在します。そのようなときにUNION ALLでまずすべての行を取得し、後からアプリケーション側で重複行の精査を行うアプローチを採用することも可能です。
ベストプラクティスとしては、結合するSELECT文の設計を事前にきちんと行い、列数やデータ型を統一しておくことが挙げられます。これにより、保守性や見通しの良さが大きく向上します。
実務で使える具体的なパターン
-- パターン1:年度別に分割されたテーブルの統合
SELECT
order_id,
customer_id,
order_date,
amount,
'2023' as fiscal_year
FROM orders_2023
UNION ALL
SELECT
order_id,
customer_id,
order_date,
amount,
'2024' as fiscal_year
FROM orders_2024
UNION ALL
SELECT
order_id,
customer_id,
order_date,
amount,
'2025' as fiscal_year
FROM orders_2025
ORDER BY order_date DESC;
-- パターン2:異なる条件のデータを統合して分析
SELECT
product_id,
'high_value' as segment,
SUM(quantity) as total_quantity
FROM sales
WHERE unit_price >= 1000
GROUP BY product_id
UNION ALL
SELECT
product_id,
'low_value' as segment,
SUM(quantity) as total_quantity
FROM sales
WHERE unit_price < 1000
GROUP BY product_id;
-- パターン3:複数データソースからの集約レポート
SELECT
'Online' as channel,
COUNT(*) as order_count,
SUM(amount) as total_sales
FROM online_orders
WHERE order_date >= '2025-01-01'
UNION ALL
SELECT
'Store' as channel,
COUNT(*) as order_count,
SUM(amount) as total_sales
FROM store_orders
WHERE order_date >= '2025-01-01';
ベストプラクティスまとめ
| プラクティス | 説明 | メリット |
|---|---|---|
| 事前設計 | 列構造を統一してから実装 | エラー防止、保守性向上 |
| 適切な選択 | 重複の必要性でUNION/UNION ALLを使い分け | パフォーマンス最適化 |
| コメント記述 | 複雑なクエリには目的を明記 | チーム内での理解促進 |
| 段階的構築 | 小さく作って検証してから拡張 | デバッグ効率化 |
| インデックス活用 | WHERE句で絞り込む列にインデックス | 処理速度向上 |
参考リンク
まとめ・総括
UNIONとUNION ALLを使いこなすことで、複数のSELECT結果を効果的に一つにまとめることができ、データ分析や集計の効率が向上します。
UNIONは重複行を除去するため、ユニークなデータを取得したいシーンで役立ちます。一方、UNION ALLは重複を含めることでパフォーマンスを高め、大量データの集約処理にも向いています。
カラム数やデータ型の揃え方、ORDER BY句の扱いなど、基本的な注意点を守ることで、エラーを防ぐだけでなく、クエリの可読性・保守性も高められます。
UNIONとUNION ALLを正しく使い分け、さらにJOINなどの他のSQL機能と組み
合わせることで、柔軟かつ効率的なデータ操作が可能になります。状況に応じた最適な選択によって、業務上の集計や分析を円滑に進めましょう。
重要ポイントの再掲
- UNION: 重複を自動削除、ユニークな結果が必要な場合に使用
- UNION ALL: すべての行を保持、パフォーマンス重視の場合に使用
- 列構造: 列数とデータ型を必ず揃える
- ORDER BY: 最後に1回だけ指定する
- 使い分け: 要件に応じて最適な演算子を選択
データベースエンジニアリングに関心をお持ちの方へ
SQLのセット演算子をはじめ、データベース設計やパフォーマンスチューニングなど、データエンジニアリングの世界は日々進化し続けています。こうした技術への探究心と、実務での課題解決に情熱を持つ方々と共に働けることを、私たちは何より大切にしています。
私たちのチームでは、SQLを活用した大規模データ処理基盤の構築や、最新のデータベース技術を用いたシステム開発に取り組んでいます。技術的な深さを追求しながら、ビジネス価値の創出にもコミットできる環境で、一緒に成長していける仲間を募集しています。
もしこの記事を通じて「もっと深く学びたい」「実践的な環境で技術を磨きたい」と感じていただけたなら、ぜひ私たちのキャリアページもご覧ください。皆さまとお会いできることを楽しみにしています!
学んだSQLを、実務で使えるスキルにしたい方へ
本記事ではSQLの基本的な考え方や使い方を解説しましたが、
「実務で使えるレベルまで身につけたい」と感じた方も多いのではないでしょうか。
SQLは、文法を理解するだけでなく、
- どんなデータ構造で使われるのか
- どんなクエリが現場で求められるのか
を意識して学ぶことで、実践力が大きく変わります。
そうした「実務を見据えたSQL学習」を進めたい方には、
完全無料で学べるプログラミングスクール ZeroCode という選択肢もあります。
- SQLを含むWeb・データベース系スキルを体系的に学べる
- 未経験者でも実務を意識したカリキュラム
- 受講料・教材費がかからない完全無料の学習環境
- 完全オンラインでスキマ学習
※学習内容や進め方を確認するだけでもOKです