【SQL】EXISTSってなに?条件に合うデータがあるか調べてみよう

こんにちは、さるまりんです。

SQLを書いていると、

EXISTS

というものを見かけることがあります。

英語の exist は「存在する」という意味なので、

「何かがあるかどうかを見るのかな?」

という感じはします。

でも、実際のSQLを見ると、

SELECT *
FROM users
WHERE EXISTS (
    SELECT 1
    FROM orders
    WHERE orders.user_id = users.id
);

のようになっていて、ちょっと不思議です。

EXISTS は何を調べているのでしょうか。

そして、

SELECT 1

1 は何なのでしょう。

今回は、SQLの EXISTS が何をしているのか、簡単な例を使って見ていきたいと思います。


EXISTSってなに?

EXISTS は、

条件に合うデータが存在するかどうか

を調べるために使います。

例えば、こんな users テーブルがあるとします。

id name
1 さるまりん
2 ゴリラ
3 オカピ

そして、注文の情報が入った orders テーブルがあるとします。

id user_id item
1 1 りんご
2 1 バナナ
3 3 コーヒー

user_idusers テーブルの id と対応しています。

このデータを見ると、

  • さるまりんには注文がある
  • ゴリラには注文がない
  • オカピには注文がある

という状態です。

ここから、

「注文したことがあるユーザーだけを取り出したい」

とします。

そんなときに EXISTS を使うことができます。


EXISTSを使ってみましょう

SQLを書いてみます。

SELECT *
FROM users
WHERE EXISTS (
    SELECT 1
    FROM orders
    WHERE orders.user_id = users.id
);

ちょっと長くなりました。

まずは外側から見てみます。

SELECT *
FROM users
WHERE EXISTS (
    ...
);

users テーブルからデータを取り出していますが、

WHERE EXISTS

という条件がついています。

つまり、

「条件に合う注文が存在するユーザーだけを取り出す」

という形です。

では、何が存在するかを調べているのでしょうか。

それが EXISTS の中です。

SELECT 1
FROM orders
WHERE orders.user_id = users.id

今見ているユーザーの id と同じ user_id を持つ注文があるかどうかを調べています。

例えば、さるまりんの id1 です。

そのときは、

orders.user_id = 1

になる注文があるかを探します。

ありますね。

そのため、さるまりんは結果に含まれます。

一方、ゴリラの id2 です。

orders.user_id = 2

になる注文はありません。

そのため、ゴリラは結果に含まれません。

オカピの id3 なので、対応する注文があります。

結果は、

id name
1 さるまりん
3 オカピ

となります。

EXISTS の中に書いた条件に合うデータが、

あるか、ないか。

そこを見ているんですね。


SELECT 1の「1」ってなに?

ここで気になるのが、

SELECT 1

です。

なぜ 1 なのでしょうか。

EXISTS が知りたいのは、

条件に合う行が存在するかどうか

です。

その行から何かの値を取り出して使いたいわけではありません。

そのため、

SELECT 1

1 自体に特別な意味があるわけではありません。

「条件に合う行があるか」を調べるための書き方としてよく使われています。

もちろん、

SELECT *

と書いても動きます。

ですが、取得した値は使わないので、

「存在するかどうかだけを調べています」

ということが分かりやすい SELECT 1 がよく使われています。

EXISTS を見たときは、

SELECT 1だから「1」を取得している

と考えるより、

条件に合う行はある?

と考えると分かりやすそうです。


NOT EXISTSもある

反対に、

「条件に合うデータが存在しない」

ことを調べることもできます。

そのときに使えるのが、

NOT EXISTS

です。

例えば、

注文したことがないユーザー

を探してみます。

SELECT *
FROM users
WHERE NOT EXISTS (
    SELECT 1
    FROM orders
    WHERE orders.user_id = users.id
);

先ほどとは反対ですね。

注文がある、さるまりんとオカピは条件に当てはまりません。

注文がないゴリラだけが残ります。

id name
2 ゴリラ

EXISTS が、

「ある?」

なら、

NOT EXISTS は、

「ない?」

と考えると、最初は分かりやすいかもしれません。

この場合は、

「注文している人は誰?していないのは誰?」

ということですね。


EXISTSは「何を取るか」ではなく「あるか」を見る

SQLでは、

SELECT name

や、

SELECT *

のように、

「何を取り出すか」

を考えることが多いと思います。

EXISTS は少し考え方が違います。

知りたいのは、中のSQLからどんな値を取り出せるかではなく、

条件に合うデータが存在するかどうか

です。

WHERE EXISTS (
    SELECT 1
    FROM orders
    WHERE orders.user_id = users.id
)

を見かけたら、

「今見ているユーザーに対応する注文はあるかな?」

というように読んでみると、意味をつかみやすくなると思います。


まとめ

今回は、SQLの EXISTS について見てきました。

EXISTS は、

条件に合うデータが存在するかどうか

を調べるときに使えます。

EXISTS (...)

なら、

「ある?」

NOT EXISTS (...)

なら、

「ない?」

という感じです。

そして、

SELECT 1

1 を取得することが目的ではなく、その条件に合う行が存在するかどうかを見ています。

SQLには、INJOIN などを使って似たような結果を得られる場合もあります。

では、EXISTS とは何が違うのでしょうか。

そのあたりも、また別の記事で見てみたいと思います。

読んでくださってありがとうございます。

それではまた!