こんにちは、さるまりんです。
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_id が users テーブルの 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 を持つ注文があるかどうかを調べています。
例えば、さるまりんの id は 1 です。
そのときは、
orders.user_id = 1
になる注文があるかを探します。
ありますね。
そのため、さるまりんは結果に含まれます。
一方、ゴリラの id は 2 です。
orders.user_id = 2
になる注文はありません。
そのため、ゴリラは結果に含まれません。
オカピの id は 3 なので、対応する注文があります。
結果は、
| 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には、IN や JOIN などを使って似たような結果を得られる場合もあります。
では、EXISTS とは何が違うのでしょうか。
そのあたりも、また別の記事で見てみたいと思います。
読んでくださってありがとうございます。
それではまた!