
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は奥が深いですね~!
《関連記事》

