Oracle INTERSECT 集合演算子 2つのテーブルの重複しているレコードを抽出する方法

スポンサーリンク
スポンサーリンク

集合演算子 「INTERSECT」

2つのテーブルを比較して、共通するレコードを抽出することができるのが、集合演算子である「INTERSECT」です。

ちなみに集合演算子を使った場合、基本的に重複行は抽出されません。

INTERSECT構文

以下が、「INTERSECT」の基本的な構文です。

SELECT 列1, 列2,・・・ FROM <テーブル名1>
INTERSECT
SELECT 列1, 列2,・・・ FROM <テーブル名2>;

検証用のデータの用意

以下の2つのテーブルとデータを使って「INTERSECT」の動きを見ていきます。

ANIMAL1テーブル
id name address
001 いるか
002 うさぎ
003 ぺんぎん
004 いるか
ANIMAL2テーブル
id name address
001 いるか
002 うさぎ
005 ふくろう

検証用データのSQL

--animal1テーブルとデータの作成
CREATE TABLE animal1
(
    id       VARCHAR2(10)
    ,name    VARCHAR2(20)
    ,address VARCHAR2(20)
);
INSERT INTO animal1 ( id, name, address ) VALUES ('001', 'いるか', '海');
INSERT INTO animal1 ( id, name, address ) VALUES ('002', 'うさぎ', '陸');
INSERT INTO animal1 ( id, name, address ) VALUES ('003', 'ぺんぎん', '空');
INSERT INTO animal1 ( id, name, address ) VALUES ('004', 'いるか', '海');

----animal2テーブルとデータの作成
CREATE TABLE animal2
(
    id       VARCHAR2(10)
    ,name    VARCHAR2(20)
    ,address VARCHAR2(20)
);

INSERT INTO animal2 ( id, name, address ) VALUES ('001', 'いるか', '海');
INSERT INTO animal2 ( id, name, address ) VALUES ('002', 'うさぎ', '陸');
INSERT INTO animal2 ( id, name, address ) VALUES ('005', 'ふくろう', '空');

検証用データの実行結果

SQL> CREATE TABLE animal1
  2  (
  3      id       VARCHAR2(10)
  4      ,name    VARCHAR2(20)
  5      ,address VARCHAR2(20)
  6  );

表が作成されました。

SQL> INSERT INTO animal1 ( id, name, address ) VALUES ('001', 'いるか', '海');
1行が作成されました。
SQL> INSERT INTO animal1 ( id, name, address ) VALUES ('002', 'うさぎ', '陸');
1行が作成されました。
SQL> INSERT INTO animal1 ( id, name, address ) VALUES ('003', 'ぺんぎん', '空');
1行が作成されました。
SQL> INSERT INTO animal1 ( id, name, address ) VALUES ('004', 'いるか', '海');
1行が作成されました。

SQL> CREATE TABLE animal2
  2  (
  3      id       VARCHAR2(10)
  4      ,name    VARCHAR2(20)
  5      ,address VARCHAR2(20)
  6  );

表が作成されました。

SQL> INSERT INTO animal2 ( id, name, address ) VALUES ('001', 'いるか', '海');
1行が作成されました。
SQL> INSERT INTO animal2 ( id, name, address ) VALUES ('002', 'うさぎ', '陸');
1行が作成されました。
SQL> INSERT INTO animal2 ( id, name, address ) VALUES ('005', 'ふくろう', '空');
1行が作成されました。

INTERSECTの実行例

「ANIMAL1」テーブルと「ANIMAL2テーブル」の2つのテーブルから共通のレコードを抽出してみましょう。
今回の例ですと、IDが001の「いるか」と「うさぎ」のレコードが抽出されるはずですね。

イメージを掴むためにベン図を書いてみました。

INTERASECTのSQL

以下のSQLを実行してみましょう。

SELECT id, name ,address FROM animal1
INTERSECT
SELECT id, name ,address FROM animal2;

INTERASECTの実行結果

SQL> SELECT id, name ,address FROM animal1
  2  INTERSECT
  3  SELECT id, name ,address FROM animal2;

ID         NAME       ADDRESS
---------- ---------- --------------------
001        いるか     海
002        うさぎ     陸

想定どおりのレコードが取得できていますね\(^o^)/

INTERSECTは重複行を取得しない

冒頭でも記述したように「INTERSECT」は重複行を取得しません。というか集合演算子は、重複行を取得しません。

上記までの検証結果だと重複行が出力されないのかが判別つかないので、「ANIMAL1」テーブルと「ANIMAL2テーブル」の2つのテーブルから「name」カラムと「address」カラムに絞って共通のレコードがあるか抽出してみましょう。

イメージを掴むためにベン図を書いてみました。
先程と違う点は、IDが「001」の「いるか」とIDが「004」の「いるか」がカラムを絞って抽出したことによって両方とも「name:いるか」の「address:海」のレコードになっている点です。重複行が出力されるのであれば、「いるか」が2行出力されるはずですね\(^o^)/

INTERASECTのSQL

以下のSQLを実行してみましょう。

SELECT name ,address FROM animal1
INTERSECT
SELECT name ,address FROM animal2;

INTERASECTの実行結果

SQL> SELECT name ,address FROM animal1
  2  INTERSECT
  3  SELECT name ,address FROM animal2;

NAME       ADDRESS
---------- --------------------
いるか     海
うさぎ     陸

想定どおりの結果ですね。「いるか」のレコードは1行しか抽出しませんでした。このことから重複行は取得しないということがわかったと思います。

「ALL」オプションについて

ちなみに、「ALL」オプションを付与することで重複行を取得するようにできる集合演算子もあります。「INTERSECT」演算子についてもOracle以外のDBMSだと「ALL」オプション使えるものもあるみたいです。

現在検証で使っているOracleの11g時点では「INTERSECT」に「ALL」オプションは使えないはずです。。。!残念(´・ω・`)

コメント

タイトルとURLをコピーしました