SQLでデータの存在チェックを行うために利用される「exists」句ですが、しっかりと使い方を理解出来ていない方も多いようです。
本記事では、SQL初心者の方向けにMySQLを用いて「exists」句の基本的な使い方をサンプルコードを交えながらご紹介していきたいと思います。
目次
SQLで利用する「exists」句とは?
まずはSQL文における「exists」句の考え方についてご紹介していきたいと思います。
しっかりと概要を確認してサンプルコードの役割を理解するようにしましょう。
exists句はデータの存在チェックで利用される
SQLで「exists」句を利用する目的としては「データの存在チェック」を行うためです。
exists句の主な利用方法としては、相関副問合せ(相関サブクエリ)と呼ばれる方法を使用します。
exists句をwhere条件として記述し、主問合せ(メインクエリ)のテーブル列を参照する方法が一般的となっています。
「exists」の否定形 「not exists」も合わせて覚えておこう
exists句では該当データが存在する場合には「true」、存在しない場合「false」を返却します。
一方で「not exists」では該当データが存在する場合「false」、存在しない場合は「true」を返却します。
問合せ内容に合った内容で、より適切なSQLを組み立てるようにしましょう。
MySQLでexists句を使ってみよう!
ここからは実際にMySQL環境におけるexists句の使い方をサンプルコードを交えながらご紹介していきたいと思います。
テスト用のサンプルデータ
サンプルとしては下記の2つのテーブルを用意しました。
sample_user
+------+---------------+ | id | name | +------+---------------+ | 1 | ポテパン1 | | 2 | ポテパン2 | | 3 | ポテパン3 | +------+---------------+
sample_order
+----------+--------------+---------------------+---------+ | order_id | product_name | order_date | user_id | +----------+--------------+---------------------+---------+ | 1 | ラーメン | 2020-01-15 13:08:41 | 1 | | 2 | カレー | 2020-01-15 13:09:26 | 1 | | 3 | 寿司 | 2020-01-15 13:09:45 | 2 | +----------+--------------+---------------------+---------+
existsを実際に利用したサンプルSQL
では上記のテーブルを利用して実際にexists句を使用したサンプルSQLをご紹介したいと思います。
今回のサンプルではお店で注文したことがあるユーザーを抽出する想定でSQLを作成していきます。
実際のSQLが下記の通りとなります。
select * from sample_user where exists (select * from sample_order where sample_order.user_id = sample_user.id);
サンプルSQLを実行した結果が下記の通りとなります。
+------+---------------+ | id | name | +------+---------------+ | 1 | ポテパン1 | | 2 | ポテパン2 | +------+---------------+
サンプルSQLでは「sample_order」テーブルの「user_id」と一致する「id」が「sample_user」テーブルに存在するかを確認して、過去に一度でも注文したことのあるユーザーデータを抜き出しています。
「sample_order」テーブルの「user_id」列にはidが「1」と「2」のデータが登録されていますが、idが「3」のユーザーに関してはデータが登録されていないため、検索結果として出力されていないことがご確認頂けます。
not exists句を利用して注文が登録されていないユーザーだけを抽出してみよう
今度は上記のサンプルとは逆に「sample_order」テーブルに注文が登録されていないユーザーのデータを抽出してみましょう。
サンプルSQLの変更ポイントはexists句をnot exists句に変更するだけです。
select * from sample_user where not exists (select * from sample_order where sample_order.user_id = sample_user.id);
実行結果が下記の通りとなります。
+------+---------------+ | id | name | +------+---------------+ | 3 | ポテパン3 | +------+---------------+
exists句のサンプルとは逆に、「sample_order」テーブルに登録されていない、未注文のユーザーのみが抽出されていることがご確認頂けます。
existsはinner joinを使ったSQLで書き換えることが可能
exists句に関しては、「inner join」というテーブル結合の方法で実現させることが可能です。
exists句よりもinner joinを利用した方が処理速度が早くなるケースも多いため、exists句の取り扱い方法を理解すると同時にinner joinの記述ではどうすれば良いのかも合わせて理解しておきましょう。
サンプルSQLをinner joinを用いて書き換えてみよう
実際に上記のexists句を使用したサンプルSQLからinner joinを使用したSQLへ書き換えた結果が下記となります。
select id, name from sample_user inner join (select distinct user_id from sample_order) as s_order on s_order.user_id = sample_user.id;
実行した結果は下記の通りとなります。
+------+---------------+ | id | name | +------+---------------+ | 1 | ポテパン1 | | 2 | ポテパン2 | +------+---------------+
サンプルではデータ数が少ないこともあり、処理速度に大きな影響はありませんが、何万件といったデータを処理する場合exists句を使用せずinner joinを利用する方法も検討してみてください。
さいごに:MySQL以外のデータベースでもexists句の利用は可能
本記事では、MySQL環境での「exists」句の利用方法についてご紹介してきました。
exists句はSQLにおける基本構文のためMySQL以外のデータベースでも利用することが基本的には可能です。
一方でexists句を利用する場合、処理が遅くなることも考えられるため、joinを利用した取得方法についても検討してみましょう。
詳しくは後述するサンプルSQLをご参照ください。