Oracle SQL SELECT4 : 集合演算子 UNION,INTERSECT,MINUS
集合演算子は2個の問い合わせ結果を1個の結果に結合する演算子です。以下に集合演算子を示します。
- 各々の問い合わせ結果の全ての行で、重複行は含まないものを返す。
- 各々の問い合わせ結果の全ての行で、重複行は含む。
- 集合演算子のソートについて
- 各々の問い合わせ結果で共に存在する行で、重複行は含まない。
- 最初の問い合わせ結果の行から、次の問い合わせで返る行を含まないもの。重複行は含まない。
これらの演算子の説明をする為に、これまで使用してきたテーブルTM_商品を例にとって説明していきます。以下にテーブルの内容一覧を全て表示します。
SQL> SELECT * FROM TM_商品;
商品コード 商品名 商品区分 仕入単価 売上単価
---------- ---------------------------------------- -------------------- ---------- ----------
1 PC-9001 デスクトップパソコン 65000 98000
2 PC-9002 デスクトップパソコン 95000 120000
3 PC-9003 デスクトップパソコン 150000 190000
4 NOTE-1010 ノートパソコン 125000 188000
5 NOTE-1020 ノートパソコン 145000 200000
6 NOTE-1030 ノートパソコン 155000 220000
7 PRT-3001 プリンタ 45000 88000
8 PRT-4001 プリンタ 115000 180000
9 CRT-1001 ディスプレイ 45000 78000
10 CRT-2001 ディスプレイ 55000 98000
11 HUB-A001 ネットワーク 20000 40000
商品コード 商品名 商品区分 仕入単価 売上単価
---------- ---------------------------------------- -------------------- ---------- ----------
12 HUB-B001 ネットワーク 40000 60000
12行が選択されました。
おすすめ書籍
- 図解入門よくわかる最新Oracleデータベースの基本と仕組み[第4版] (How‐nual Visual Guide Book)
- Oracleの基本 ~データベース入門から設計/運用の初歩まで
- [改訂第4版]SQLポケットリファレンス
UNION (各々の問い合わせ結果の全ての行で、重複行は含まないものを返す。)
SQL> SELECT * FROM TM_商品 WHERE 仕入単価 < 50000
2 UNION
3 SELECT * FROM TM_商品 WHERE 仕入単価 < 40000;
商品コード 商品名 商品区分 仕入単価 売上単価
---------- ---------------------------------------- -------------------- ---------- ----------
7 PRT-3001 プリンタ 45000 88000
9 CRT-1001 ディスプレイ 45000 78000
11 HUB-A001 ネットワーク 20000 40000
12 HUB-B001 ネットワーク 40000 60000
1行目のSELECT文は仕入単価が50,000円未満の商品を全て結果として返すものであり、商品コードが7,9,11,12です。また3行目のSELECT文は仕入単価が40,000円未満の商品を選択し、商品コードが11となります。商品コードが11は重複行となり、結果として上記の4行しか返されません。
尚、以下の様に3個のSELECT文をUNIONで結合した例を示します。5行目のSELECT文は固定値としてのデータを結果に含める為のもので、SELECT句に並べるデータの個数は1行目及び3行目で返される列の個数に合わせなければなりません。
SQL> SELECT * FROM TM_商品 WHERE 仕入単価 < 50000
2 UNION
3 SELECT * FROM TM_商品 WHERE 仕入単価 < 40000
4 UNION
5 SELECT 0,'ダミー商品名','ダミー商品区分',1000,1000 FROM DUAL;
商品コード 商品名 商品区分 仕入単価 売上単価
---------- ---------------------------------------- -------------------- ---------- ----------
0 ダミー商品名 ダミー商品区分 1000 1000
7 PRT-3001 プリンタ 45000 88000
9 CRT-1001 ディスプレイ 45000 78000
11 HUB-A001 ネットワーク 20000 40000
12 HUB-B001 ネットワーク 40000 60000
列の個数を合わせなかった例を以下に示します。
SQL> SELECT * FROM TM_商品 WHERE 仕入単価 < 50000 2 UNION 3 SELECT * FROM TM_商品 WHERE 仕入単価 < 40000 4 UNION 5 SELECT 0,'ダミー商品名','ダミー商品区分',1000 FROM DUAL; SELECT * FROM TM_商品 WHERE 仕入単価 < 40000 * エラー行: 3: エラーが発生しました。 ORA-01789: 問合せブロックにある結果の列数が正しくありません
UNION ALL (各々の問い合わせ結果の全ての行で、重複行は含む。)
SQL> SELECT * FROM TM_商品 WHERE 仕入単価 < 50000
2 UNION ALL
3 SELECT * FROM TM_商品 WHERE 仕入単価 < 40000;
商品コード 商品名 商品区分 仕入単価 売上単価
---------- ---------------------------------------- -------------------- ---------- ----------
7 PRT-3001 プリンタ 45000 88000
9 CRT-1001 ディスプレイ 45000 78000
11 HUB-A001 ネットワーク 20000 40000
12 HUB-B001 ネットワーク 40000 60000
11 HUB-A001 ネットワーク 20000 40000
UNIONの例のSQLをUNION ALLに変更すると、UNIONとの違いがはっきりすると思います。結果として返される商品コードが7,9,11,12は最初のSELECT文での結果の行であり、最後の商品コードが11が2番目のSELECT文の結果の行を示しています。
ソートについて
ORDER BY句により返される結果をソートする場合は、結果の列の名称ではなく列の位置を指定しなければなりません。以下に商品コード及び、仕入単価でソートする様子を示します。尚、最後のエラーの発生しているSQL文はORDER BY句に列名を指定したものを示しています。
SQL> SELECT * FROM TM_商品 WHERE 仕入単価 < 50000
2 UNION ALL
3 SELECT * FROM TM_商品 WHERE 仕入単価 < 40000
4 ORDER BY 1;
商品コード 商品名 商品区分 仕入単価 売上単価
---------- ---------------------------------------- -------------------- ---------- ----------
7 PRT-3001 プリンタ 45000 88000
9 CRT-1001 ディスプレイ 45000 78000
11 HUB-A001 ネットワーク 20000 40000
11 HUB-A001 ネットワーク 20000 40000
12 HUB-B001 ネットワーク 40000 60000
SQL> SELECT * FROM TM_商品 WHERE 仕入単価 < 50000
2 UNION ALL
3 SELECT * FROM TM_商品 WHERE 仕入単価 < 40000
4 ORDER BY 4;
商品コード 商品名 商品区分 仕入単価 売上単価
---------- ---------------------------------------- -------------------- ---------- ----------
11 HUB-A001 ネットワーク 20000 40000
11 HUB-A001 ネットワーク 20000 40000
12 HUB-B001 ネットワーク 40000 60000
7 PRT-3001 プリンタ 45000 88000
9 CRT-1001 ディスプレイ 45000 78000
SQL> SELECT * FROM TM_商品 WHERE 仕入単価 < 50000
2 UNION ALL
3 SELECT * FROM TM_商品 WHERE 仕入単価 < 40000
4 ORDER BY 商品区分;
ORDER BY 商品区分
*
エラー行: 4: エラーが発生しました。
ORA-00904: 列名が無効です。
エラーが発生するORDER BY句の列名指定も以下の様に、副問い合わせにすれば可能になります。
SQL> SELECT * FROM
2 (
3 SELECT * FROM TM_商品 WHERE 仕入単価 < 50000
4 UNION
5 SELECT * FROM TM_商品 WHERE 仕入単価 < 40000
6 UNION
7 SELECT 0,'ダミー商品名','ダミー商品区分',1000,1000 FROM DUAL
8 )
9 ORDER BY 商品コード DESC;
商品コード 商品名 商品区分 仕入単価 売上単価
---------- ---------------------------------------- -------------------- ---------- ----------
12 HUB-B001 ネットワーク 40000 60000
11 HUB-A001 ネットワーク 20000 40000
9 CRT-1001 ディスプレイ 45000 78000
7 PRT-3001 プリンタ 45000 88000
0 ダミー商品名 ダミー商品区分 1000 1000
INTERSECT (各々の問い合わせ結果で共に存在する行で、重複行は含まない。)
INTERSECTの例を以下に示します。この演算子は論理演算で言うところのAND演算の様な働きをします。1行目の仕入単価が40,000円より高いものと、3行目の仕入単価が50,000円未満のものとのANDをとっています。
SQL> SELECT * FROM TM_商品 WHERE 仕入単価 > 40000
2 INTERSECT
3 SELECT * FROM TM_商品 WHERE 仕入単価 < 50000;
商品コード 商品名 商品区分 仕入単価 売上単価
---------- ---------------------------------------- -------------------- ---------- ----------
7 PRT-3001 プリンタ 45000 88000
9 CRT-1001 ディスプレイ 45000 78000
MINUS (最初の問い合わせ結果の行から、次の問い合わせで返る行を含まないもの。重複行は含まない。)
MINUSの例を以下に示します。この演算子は最初のSELECT文の結果から、次のSELECT文の結果を差し引く様な働きをします。1行目はTM_商品の全てを返し、その結果から3行目の仕入単価が50,000円未満の商品を省く結果となります。
SQL> SELECT * FROM TM_商品
2 MINUS
3 SELECT * FROM TM_商品 WHERE 仕入単価 < 50000;
商品コード 商品名 商品区分 仕入単価 売上単価
---------- ---------------------------------------- -------------------- ---------- ----------
1 PC-9001 デスクトップパソコン 65000 98000
2 PC-9002 デスクトップパソコン 95000 120000
3 PC-9003 デスクトップパソコン 150000 190000
4 NOTE-1010 ノートパソコン 125000 188000
5 NOTE-1020 ノートパソコン 145000 200000
6 NOTE-1030 ノートパソコン 155000 220000
8 PRT-4001 プリンタ 115000 180000
10 CRT-2001 ディスプレイ 55000 98000
8行が選択されました。