今回の初心者訓練所#21は、WHERE句で使用されるサブクエリの結果が存在するかどうかを判定するEXISTS句について説明していきます。データの存在チェックをおこなう場合に、便利で可読性もよい方法なので、是非、使い方を覚えましょう。いつもの「SQLite」を使用して進めていきますので、「SQLite」をインストールしてから読み進めてください。
EXISTS句
EXISTS句は、WHERE句の条件文で使用され指定したサブクエリの結果が1件以上の行を返す場合に、「真(TRUE)」、それ以外は「偽(FALSE)」となります。結果が真となった場合にのみ、メインのクエリが実行されます。このように、特定の条件に一致するデータの存在チェックに便利な句です。
また、EXISTS句はサブクエリが結果を見つけた時点で評価を終了し無駄なデータの取得を行わないので、大規模なデータでチェックを行う場合に効率的に動作することがあります。ただし、サブクエリが非常に複雑な場合はパフォーマンスが低下する恐れがありますので注意してください。
構文は以下となります。
where EXISTS ( サブクエリ ) |
それでは、実際のデータを利用して確認するために、確認用の社員テーブル(tbl_employees)と部署テーブル(tbl_dept)を作成してデータを挿入してみましょう。
create table tbl_employees (emp_code integer, emp_name text, kana text , gender text , birthday text , dept_code integer); |
create table tbl_dept (dept_code integer, dept_name text, valid_flg text); |
insert into tbl_employees values (101,'HoriiTaro','ホリイタロウ','M','1970-12-27',100) , (102,'IshimuraHana','イシムラハナ','F','1981-09-01',200) , (103,'KitajimaRuna','キタジマルナ','F','1981-11-30',300) , (104,'MuroiYuri','ムロイユリ','F','1982-02-12',400) , (105,'KitazawaAika','キタザワアイカ','F','1980-08-05',400) , (106,'MitaniKoukiti','ミタニコウキチ','M','1979-03-16',200); |
insert into tbl_dept values (100,'営業部','1') , (200,'人事部','1') , (300,'総務部','1'); |
出力フォーマットを調整して、SELECT文でそれぞれのテーブルの登録内容を確認してみましょう。
.headers on (ヘッダ情報を出力) .mode column (カラム毎に左揃え出力) select * from tbl_employees; select * from tbl_dept; |
社員テーブルに6件、部署テーブルに3件のデータが作成されていることが確認できます。
それでは、作成したデータからEXISTS句を使用して、社員テーブルの部署コードが部署テーブルに存在する社員のみを抽出してみましょう。
以下のSELECT文で確認してみましょう。
select emp.emp_name,emp.dept_code from tbl_employees as emp where EXISTS ( select dp.dept_code from tbl_dept as dp where dp.dept_code = emp.dept_code ); |
EXISTS句のサブクエリで、社員テーブルのdept_code毎に部署テーブルのdept_codeを比較して、部署テーブルに該当するdept_codeが存在するかチェックを行っています。
部署テーブルに該当する部署コードが存在する場合のみ、社員テーブルの該当データが表示されます。
また、社員テーブルと部署テーブルに同じ項目名「dept_code」が存在するので、それぞれのテーブル名を別名(AS句)で「emp」「dp」に変換して、使用している項目がどのテーブルの項目か分かり易いようにしています。
補足情報となりますが、上記のサブクエリのように、親のクエリの値を基に実行されるサブクエリは、相関サブクエリとよばれます。
参考までに、上記のEXISTS句を使用したクエリを内部結合で記述すると下記の様になります。
select emp.emp_name,emp.dept_code from tbl_employees as emp INNER JOIN tbl_dept as dp ON dp.dept_code = emp.dept_code; |
EXISTS句のクエリと同じ結果になることが確認できます。
内部結合では、dept_codeで社員テーブルと部署テーブルを結合しているので、両方のテーブルにdept_codeが存在するデータが抽出されます。
NOT EXISTS句
EXISTS句とは逆に、条件に一致するデータが存在しない場合に、「真(TRUE)」、それ以外は「偽(FALSE)」を返す場合は、「NOT EXISTS」を使用します。
構文は以下となります。
where NOT EXISTS ( サブクエリ ) |
先程とは逆に、NOT EXISTS句を使用して、社員テーブルのdept_codeが部署テーブルに存在しない社員のみを抽出してみましょう。
以下のSELECT文で確認してみましょう。
select emp.emp_name,emp.dept_code from tbl_employees as emp where NOT EXISTS ( select dp.dept_code from tbl_dept as dp where dp.dept_code = emp.dept_code ); |
部署テーブルに存在しない、dept_code「400」の2件が抽出されていることが確認できます。
参考までに、上記のNOT EXISTS句を使用したクエリを外部結合で記述すると下記の様になります。
select emp.emp_name,emp.dept_code from tbl_employees as emp LEFT OUTER JOIN tbl_dept as dp ON dp.dept_code = emp.dept_code where dp.dept_code IS NULL; |
内部結合と同様にdept_codeで外部結合しています。
外部結合では結合した結果、存在しないテーブルの項目は「NULL」となるので、
部署テーブルのdept_codeが「NULL」(社員テーブルに存在しているが、部署テーブルに存在していない)の条件を追加して、社員テーブルにのみ存在するデータを抽出しています。
参考までに、dept_codeが「NULL」の条件を外した場合は、以下の結果となります。
select emp.emp_name,emp.dept_code,dp.dept_code from tbl_employees as emp LEFT OUTER JOIN tbl_dept as dp ON dp.dept_code = emp.dept_code; |
説明は以上となります。
おすすめの学習コンテンツ
本記事を読み終わって、さらに学びたい方、次は問題にチャレンジしてみたい方には、以下の無料コンテンツをご用意しておりますので、ぜひ活用してみてください!
SQLiteについて
・本記事で使用したデータベース「SQLite」について解説する資料です。
SQLiteとは?他のデータベースとの違いも解説
SQLの教科書
ビックデータ時代の必須科目「SQLの教科書」(初級編)
ビックデータ時代の必須科目「SQLの教科書」(中級編 UPDATE文)
ビックデータ時代の必須科目「SQLの教科書」(中級編 テーブル結合)
ビックデータ時代の必須科目「SQLの教科書」(中級編 関数ピックアップ) NEW!!
SQL無料トライアルテスト
・TOPSIC-SQLの無料トライアルテストをご受験していただけます。
TOPSIC-SQL無料トライアルテスト
SQLコンテスト
・簡単な会員登録をするだけでSQLのオンラインコンテストに無料で参加できます。
過去に開催されたコンテストの問題にもチャレンジできます。
TOPSIC SQL CONTEST
SQL基礎解説YouTube
・「TOPSIC-SQL」を元にしたオンラインウェビナーです。
SQL-BOOT CAMP #1
ビッグデータ時代の必須科目SQLを学ぶ「実戦で通用する武器を身につけよう!」
あとがき
「初心者訓練所」の第21弾では、EXISTS句について説明してきました。EXISTS句は、特定の条件に一致するデータの存在を効率的に確認するための強力なツールであり、大規模なデータベースでのクエリ作成において特に役立ちます。EXISTS句をうまく活用して、今後の皆さんのデータベース操作やSQLクエリの作成がより効率的に進めることができれば幸いです。
(株)システムインテグレータ TOPSICチーム 元鬼軍曹 久保 司
- カテゴリ: