PostgreSQLで検索結果を結合する! INTERSECTとEXCEPTを使ってみた
目次
こんにちは。最近SQLを使う機会が多い関口です。
前回は検索結果を結合して取得する、代表的なUNIONとUNION ALLについて紹介しました。
PostgreSQLで検索結果を結合する!UNIONを使ってみた。
今回は、同じ検索結果の結合でも、UNIONとは違った結合の仕方ができる構文を紹介していきます!
検証環境
検証で使用した環境は以下の通りです。
- PostgreSQL
- 12.3
INTERSECTとは
INTERSECTは、複数の検索結果(SELECT)全てに含まれているデータを取得できる構文です。検索結果同士の項目数およびデータ型が一致している必要があります。また、INTERSECTでは、DISTINCTと同様に、結果から重複している行を削除して取得します。
今回使用するテーブルは下記の通り作成しました。
// テーブル作成SQL
create table public.table_a (
user_id integer not null
, name character varying(50)
, target_date date
);
create table public.table_b (
user_id integer not null
, name character varying(50)
, target_date date
);
// テーブル内データ
SELECT * FROM table_a;
user_id | name | target_date
---------+------+-------------
1 | 杉本 | 2022-04-30
1 | 杉本 | 2022-05-01
2 | 白石 | 2022-04-30
2 | 白石 | 2022-05-01
2 | 白石 | 2022-05-02
3 | 尾形 | 2022-04-30
4 | 月島 | 2022-05-01
5 | 鶴見 | 2022-05-02
5 | 鶴見 | 2022-05-02
(9 行)
SELECT * FROM table_b;
user_id | name | target_date
---------+------+-------------
1 | 杉本 | 2022-04-30
1 | 杉本 | 2022-05-01
2 | 白石 | 2022-04-30
2 | 白石 | 2022-05-02
3 | 尾形 | 2022-04-30
(5 行)
それでは、実際にINTERSECTを使ってみましょう!
// 実行SQL
SELECT
user_id
, name
FROM
table_a
INTERSECT
SELECT
user_id
, name
FROM
table_b;
// 実行結果
user_id | name
---------+------
1 | 杉本
2 | 白石
3 | 尾形
(3 行)
table_aとtable_bの両方に存在するデータが取得できました! 重複データも削除されていますね。複数の検索結果で、重複するデータを取得したい場合はINTERSECTを使いましょう。
INTERSECT ALLとは
INTERSECT ALLは、INTERSECTと同様に、複数の検索結果(SELECT)全てに含まれているデータを取得できる構文です。INTERSECT ALLでは、結果から重複している行もそのまま取得されます。重複チェックを行わない分、INTERSECTよりも処理速度が速くなります。
先ほど使用したSQLを、INTERSECT ALLに変えて実行してみます!
// 実行SQL
SELECT
user_id
, name
FROM
table_a
INTERSECT ALL
SELECT
user_id
, name
FROM
table_b;
// 実行結果
user_id | name
---------+------
1 | 杉本
1 | 杉本
2 | 白石
2 | 白石
3 | 尾形
(5 行)
重複チェックで削除されていたデータも取得できました! 重複を削除しなくてもいい場合は、INTERSECT ALLを使用しましょう。
EXCEPTとは
EXCEPTは、複数の検索結果(SELECT)のうち、1つめの検索結果にだけ存在するデータを取得できる構文です。検索結果同士の項目数およびデータ型が一致している必要があります。また、EXCEPTでは、DISTINCTと同様に、結果から重複している行を削除して取得します。
// 実行SQL
SELECT
user_id
, name
FROM
table_a
EXCEPT
SELECT
user_id
, name
FROM
table_b;
// 実行結果
user_id | name
---------+------
4 | 月島
5 | 鶴見
(2 行)
table_aにだけ存在するデータが取得され、重複データは削除されていますね。複数の検索結果で、1つの検索結果にだけ存在するデータを取得したい場合はEXCEPTを使いましょう。
EXCEPT ALLとは
EXCEPT ALLは、EXCEPTと同様に、複数の検索結果(SELECT)のうち、1つめの検索結果にだけ存在するデータを取得できる構文です。EXCEPT ALLでは、結果から重複している行もそのまま取得されます。重複チェックを行わない分、EXCEPTよりも処理速度が速くなります。
先ほど使用したSQLを、EXCEPT ALLに変えて実行してみます!
// 実行SQL
SELECT
user_id
, name
FROM
table_a
EXCEPT ALL
SELECT
user_id
, name
FROM
table_b;
// 実行結果
user_id | name
---------+------
2 | 白石
4 | 月島
5 | 鶴見
5 | 鶴見
(4 行)
重複チェックで削除されていたデータも取得できました! EXCEPTでは取得されていなかった「白石」が取得されているのは、table_bよりtable_aに「白石」が1つ多く存在するためです。重複を削除しなくてもいい場合は、EXCEPT ALLを使用しましょう。
まとめ
いかがでしたでしょうか。
UNIONもINTERSECTもEXCEPTも、基本的な使い方は同じです。用途にあわせて使いわけていきたい今日この頃。SQLは奥が深いですね~!
《関連記事》


