【初学者必見!】SQLの基本、実務使用例を徹底解説!EXISTS と IN の違い編

【初学者必見!】SQLの基本、実務使用例を徹底解説!EXISTS と IN の違い編 SQL

※この記事にはプロモーションが含まれています。

ふりかえり

筆者
筆者

本記事は、SQLの基本、実務使用例編になります。

SQLの基礎に関しましては、

【初学者必見!】SQLの超基礎編の記事をご覧くださいませ。

A子
A子

本編に入ります!

INと EXISTSの違い

筆者
筆者

INと EXISTSの違いの一覧になります。

項目INEXISTS
本質値の比較(リストに含まれるか)存在の確認(1件でも存在するか)
主な使い方「この値は、あのリストに含まれているか?」を調べる「この条件のデータが存在するか?」を調べる
処理対象値(=値の集合)行の存在有無
パフォーマンス面小規模データ向き(リストと比較)大規模データに強い(途中で打ち切れる)
NULL の扱い注意が必要(NULLがあると結果が変わる)NULLの影響を受けにくい
結びつけ結びつけなくても動く(値比較なので)通常はメインクエリとの結びつきが必要

A子
A子

INは値の比較をして、EXISTSは存在の確認をするんだね。

筆者
筆者

はい、そうです!

具体的にどんな感じで使用するのか、解説していきます。

実務レベルの使用例を見ていこう!

筆者
筆者

実際に、SQLを使用してデータを確認していきましょう。

SQLに関しては以下を使用して解説していきます。

create table文、select文、insert文、update文、delete文、

drop table文、につきましては、過去にアップロードした

【初学者必見!】SQLの超基礎編の記事をご覧くださいませ。

A子
A子

目次の、「ふりかえり」のところにそれぞれの記事のリンクが

貼ってあるよ!

または、サイドバーのカテゴリーにSQLがあるから、そちらからでも

参照できます!

Oracle Live SQLを使用して、SQLの動きを確認していきます。

[事前準備]今回、実行するSQLの一覧

-- 申請管理情報テーブルの作成
create table 申請管理情報 (
    STAFF_NO varchar2(10) not null,   -- 職員番号 (Staff Number) 
    APPLI_NO varchar2(10) not null,   -- 申請番号 (Application Number) 
    APPLI_DATE date,                  -- 申請年月日 (Application Date) 
    DEPARTMENT varchar2(10),          -- 部署名(Department)
    constraint PK_申請管理情報 primary key (STAFF_NO, APPLI_NO)

);
create table 申請内容の詳細 (
    職員番号          varchar2(10) not null,  -- 親テーブルの STAFF_NO に対応
    申請番号          varchar2(10) not null,  -- 親テーブルの APPLI_NO に対応
    申請内容の詳細    varchar2(100),          -- 申請の詳細内容を格納するカラム
    constraint PK_申請内容の詳細 primary key (職員番号, 申請番号),
    constraint FK_申請内容の詳細 foreign key (職員番号, 申請番号)
        references 申請管理情報 (STAFF_NO, APPLI_NO)
);

insert into 申請管理情報 (STAFF_NO, APPLI_NO, APPLI_DATE, DEPARTMENT) 
values ('1001', 'A001', TO_DATE('2024-02-25', 'YYYY-MM-DD'),'営業');
insert into 申請管理情報 (STAFF_NO, APPLI_NO, APPLI_DATE, DEPARTMENT) 
values ('1001', 'A002', TO_DATE('2024-02-26', 'YYYY-MM-DD'),'営業');
insert into 申請管理情報 (STAFF_NO, APPLI_NO, APPLI_DATE, DEPARTMENT) 
values ('1002', 'A003', TO_DATE('2024-02-27', 'YYYY-MM-DD'),'開発');
insert into 申請管理情報 (STAFF_NO, APPLI_NO, APPLI_DATE, DEPARTMENT) 
values ('1002', 'a003', TO_DATE('2024-01-27', 'YYYY-MM-DD'),'開発');
insert into 申請管理情報 (STAFF_NO, APPLI_NO, APPLI_DATE, DEPARTMENT) 
values ('1003', 'A004', TO_DATE('2024-02-28', 'YYYY-MM-DD'),'営業');

insert into 申請内容の詳細 (職員番号, 申請番号, 申請内容の詳細)
values ('1001', 'A001', 'レギュラーとハイオク間違えたので、もう一回入れに行きたいです。');
insert into 申請内容の詳細 (職員番号, 申請番号, 申請内容の詳細)
values ('1001', 'A002', 'ガソリン高いから、もっと補助してほしい');
insert into 申請内容の詳細 (職員番号, 申請番号, 申請内容の詳細)
values ('1002', 'A003', 'ハイオク満タンにしちゃった');
insert into 申請内容の詳細 (職員番号, 申請番号, 申請内容の詳細)
values ('1002', 'a003', 'レギュラー満タンにしちゃった');

使用例①:IN を使った例

select * 
from 申請管理情報
where (STAFF_NO, APPLI_NO) in (
  select 職員番号, 申請番号 
  from 申請内容の詳細
);

解説:

  • 申請内容の詳細 に登録されている (職員番号, 申請番号) のリストと、
  • 申請管理情報(STAFF_NO, APPLI_NO)値として照合しています。
  • つまり「申請内容が書かれている申請だけ抽出する」イメージです。

使用例②:EXISTS を使った例

ログイン者の職員番号が '1001'、申請番号が 'A001' のときに、申請内容の詳細 にデータが存在するか確認する SQL

select 1
from dual
where exists (
  select 1
  from 申請内容の詳細
  where 職員番号 = '1001'
    and 申請番号 = 'A001'
);

解説:

部分内容
select 1 from dualOracleでは1行返すためのダミー
where exists (...)存在すれば 1 が返る(結果あり)、なければ何も返らない
職員番号 = '1001' and 申請番号 = 'A001'この2つの条件で該当するレコードがあるかを確認

間違ったSQL(文法エラー)

select *
from 申請内容の詳細
where (職員番号, 申請番号) exists (
  select STAFF_NO, APPLI_NO
  from 申請管理情報
  where DEPARTMENT = '営業'
);

なぜエラーになるのか?

  • EXISTS は、左側に比較対象(列や値)を置けません!
  • 正しい使い方は、次のように単体で WHERE EXISTS (サブクエリ) という形です。
  • つまり、EXISTS は「行の存在」を調べるだけで、値の比較はしません。

正しい EXISTS の書き方に直すとこうなります

select *
from 申請内容の詳細 d
where exists (
  select 1
  from 申請管理情報 m
  where m.STAFF_NO = d.職員番号
    and m.APPLI_NO = d.申請番号
    and m.DEPARTMENT = '営業'
);

このSQLの動き

  1. 申請内容の詳細 の1行ごとに、
  2. 申請管理情報 に「一致する職員番号・申請番号」で、かつ 営業 のデータがあるかどうかをチェック。
  3. 存在すれば(=該当すれば)その行を返す

INEXISTS の違いをここで整理

比較項目IN(正しい例)EXISTS(正しい例)
書き方where (列1, 列2) in (select ...)where exists (select ... where 結び条件)
使いどころ値で一致させたいとき存在確認をしたいとき
間違いやすい書き方(列1, 列2) exists (...) ← ❌正しくは exists (...) の中で列を比較

まとめ

筆者
筆者

EXISTS と IN の違いについて解説しました。

複雑に見えますが、値の比較をしたいのか、存在の有無を確認したいのかで使用を分けるケースが多いです。

次回もお楽しみに!

この記事を書いた人
たくたく

文系出身・3年目のWeb系エンジニアです。
C#とSQLを得意としています。
同棲生活は2年目に入り、日々仲良く楽しく暮らしています。
プライベートではバイクや車で旅行に行くことが趣味です。
サンリオ好きで、中でもシナモン推しです。
お酒好きとして毎週の晩酌をリラックスタイムにしています。

たくたくをフォローする
SQLエンジニア
シェアする

コメント

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