集合演算とは
集合演算子(セット演算子)を使用すると、複数の SELECT 文の結果を1つにまとめることができる。和集合・積集合・差集合といった集合論の概念を SQL で実現する機能で、「複合問合せ(Compound Query)」とも呼ばれる。
Oracle Database では次の4つの集合演算子が使用できる。
集合演算子の種類
| 演算子 | 名称 | 説明 | 重複行 |
|---|---|---|---|
UNION |
和集合 | 両方の問合せ結果を合わせ、重複を除いた行を返す | 除外 |
UNION ALL |
和集合(全件) | 両方の問合せ結果を合わせ、重複を含む行を返す | 含む |
INTERSECT |
積集合 | 両方の問合せ結果に共通する行を返す | 除外 |
MINUS |
差集合 | 最初の問合せ結果にあり、2番目の問合せ結果にない行を返す | 除外 |
基本構文
SELECT 列1, 列2, ... FROM 表1
UNION [ALL]
SELECT 列1, 列2, ... FROM 表2;
SELECT 列1, 列2, ... FROM 表1
INTERSECT
SELECT 列1, 列2, ... FROM 表2;
SELECT 列1, 列2, ... FROM 表1
MINUS
SELECT 列1, 列2, ... FROM 表2;
各演算子の使用例
-- UNION:部門10と部門20の社員名(重複除去)
SELECT ename FROM emp WHERE deptno = 10
UNION
SELECT ename FROM emp WHERE deptno = 20;
-- UNION ALL:部門10と部門20の社員名(重複含む)
SELECT ename FROM emp WHERE deptno = 10
UNION ALL
SELECT ename FROM emp WHERE deptno = 20;
-- INTERSECT:部門10と部門20の両方に存在する社員名
SELECT ename FROM emp WHERE deptno = 10
INTERSECT
SELECT ename FROM emp WHERE deptno = 20;
-- MINUS:部門10にはいるが部門20にはいない社員名
SELECT ename FROM emp WHERE deptno = 10
MINUS
SELECT ename FROM emp WHERE deptno = 20;
集合演算の注意点
① 列数・データ型を一致させる
各 SELECT リストの列数とデータ型を一致させる必要がある。
- 列数が異なる場合 → エラー
-
データ型が異なる場合 → エラー(ただし同じデータ型グループ(例:
CHARとVARCHAR2)であれば許容される場合がある) - 集合演算では属性(グループ)の異なる型の間では暗黙的なデータ型変換は発生しない
- データ型が異なる場合は
TO_CHAR・TO_NUMBER・CASTなどの明示的なデータ型変換が必要
-- ❌ 暗黙変換はされない(文字型と数値型の混在はエラー)
SELECT empno FROM emp -- 数値型
UNION
SELECT ename FROM emp; -- 文字型 → エラー
-- ✅ 明示的変換で統一
SELECT TO_CHAR(empno) FROM emp
UNION
SELECT ename FROM emp;
② 列名・列別名の扱い
- 各
SELECTリストの列名は異なっていてもよい - 問合せ結果の列名には、最初の問合せの列名または列別名が使用される
-- 結果の列名は「部門番号」(最初のSELECTの列別名)になる
SELECT deptno AS 部門番号 FROM emp
UNION
SELECT deptno AS dept_id FROM dept; -- この別名は無視される
③ ORDER BY句の制約(試験頻出)
集合演算を含む複合問合せでの ORDER BY には重要なルールがある。
-
ORDER BY句は文の最後にのみ指定できる(各SELECT文に個別には付けられない) -
ORDER BY句は複合問合せ全体の結果を対象にソートする - ソート基準には以下を指定できる:
- 最初の問合せの列名
- 最初の問合せの列別名
- 列位置(数値)
-- ✅ 文の末尾に1つだけORDER BY
SELECT deptno, ename FROM emp WHERE deptno = 10
UNION
SELECT deptno, ename FROM emp WHERE deptno = 20
ORDER BY deptno; -- 最初のSELECTの列名を指定
-- ✅ 列位置(数値)で指定も可
ORDER BY 1; -- 1列目(deptno)で昇順ソート
-- ❌ 各SELECTに個別にORDER BYは指定できない
SELECT deptno FROM emp WHERE deptno = 10 ORDER BY deptno -- エラー
UNION
SELECT deptno FROM emp WHERE deptno = 20;
④ UNION ALL以外のソートについて
-
UNION・INTERSECT・MINUSは重複排除のためにソート処理が内部的に実行される -
ORDER BYを明示的に指定しない場合、結果の順序は保証されない
実務的な注意:順序を保証したい場合は、必ず明示的に
ORDER BYを指定すること。
集合演算子の優先順位
-
Oracle の実装では UNION・UNION ALL・INTERSECT・MINUS すべて同じ優先順位で、記述された順(左から右)に評価される
-
括弧
()を使用して評価順序を明示的に指定することを推奨
-- 括弧なし:左から右に評価(まずUNION、次にINTERSECT)
SELECT ... FROM A
UNION
SELECT ... FROM B
INTERSECT
SELECT ... FROM C;
-- 括弧あり:INTERSECTを先に評価
SELECT ... FROM A
UNION
(SELECT ... FROM B
INTERSECT
SELECT ... FROM C);
集合演算子が使えない型・制約
集合演算子には使用上の制限がある:
-
BLOB・CLOB・BFILE・VARRAY・ネストした表・LONG型の列には使用できない -
FOR UPDATEとの併用不可 -
ORDER BYリストに関数を含んだ式は使用できない(列別名を使用する)
集合演算子の比較まとめ
| 演算子 | 重複行 | INTERSECT より優先? | 内部ソート発生 | UNION ALLとの違い |
|---|---|---|---|---|
UNION |
除外 | 同じ | あり(重複排除のため) | 重複除去あり |
UNION ALL |
含む | 同じ | なし | 最速(重複除去なし) |
INTERSECT |
除外 | SQL標準では高い | あり | — |
MINUS |
除外 | 同じ | あり | — |
試験で意識したいポイントまとめ
| ポイント | 内容 |
|---|---|
| 列数の不一致 | エラーになる |
| データ型の異なる型グループ間 | 暗黙変換は行われない → 明示的変換が必要 |
| 同じ型グループ(CHARとVARCHAR2など) | 許容される場合がある |
| 結果の列名 | 最初の SELECT の列名・列別名が使われる |
| ORDER BY の位置 | 文の最後に1つだけ。各SELECTには付けられない |
| ORDER BY の指定方法 | 最初の SELECT の列名・列別名・列位置(数値) |
| UNION ALLの順序保証 | ORDER BY なしでは保証されない |
| UNION以外のソート断定は誤り | 「最初の列の昇順に並ぶ」は保証されない。ORDER BY が必要 |
| 集合演算子の優先順位 | 基本的に同じ優先順位。INTERSECT優先はSQL標準の話。括弧で明示推奨 |