SQLで条件にマッチするレコードが存在するか判定する場合のSQLについて紹介します。
レコードが存在するかを条件にする場合は、EXISTS演算子を用います。
where節で以下の書式を利用します。
レコードが存在しないことを条件にする場合は not exists が利用できます。
SELECT * FROM products WHERE EXISTS (SELECT id FROM sale)
id | model | name | category | price |
---|---|---|---|---|
1 | C-XM01 | モーダンチェア | チェア | 56000 |
2 | X-XD05 | ラージデスク | テーブル | 87000 |
3 | A-DA40 | ラウンドダイニングチェア | チェア | 28000 |
上記のテーブルが存在した場合
SELECT * FROM products WHERE EXISTS (SELECT TOP(0) * FROM products)
のSQLは何も結果を返しません。"select top(0) * from products"のSQLはレコードを全く返さないため、existsは常にfalseとなりすべてのレコードで条件にマッチしないため何も結果を返さない動作となります。
id | model | name | category | price |
---|
id | model | name | category | price |
---|---|---|---|---|
1 | C-XM01 | モーダンチェア | チェア | 56000 |
2 | X-XD05 | ラージデスク | テーブル | 87000 |
3 | A-DA40 | ラウンドダイニングチェア | チェア | 28000 |
上記のテーブルが存在した場合
SELECT * FROM products WHERE EXISTS (SELECT null)
のSQLを実行した場合、全ての行を返す結果となります。
"select null"はNULLの行を1つ返しますので、行は存在するため、existsは trueと判定されます。
すべての行で同じ結果(NULL)が返りますので、"select * from products"と同等のSQLとなり、全ての行が結果で返されます。
なお、以下のSQL文でもexists節内のselectで値が返るため、全行が結果で返されます。
SELECT * FROM productsB WHERE EXISTS (SELECT 1)
SELECT * FROM productsB WHERE EXISTS (SELECT '')
id | model | name | category | price |
---|---|---|---|---|
1 | C-XM01 | モーダンチェア | チェア | 56000 |
2 | X-XD05 | ラージデスク | テーブル | 87000 |
3 | A-DA40 | ラウンドダイニングチェア | チェア | 28000 |
id | model | name | category | price |
---|---|---|---|---|
1 | C-XM01 | モーダンチェア | チェア | 56000 |
2 | X-XD05 | ラージデスク | テーブル | 87000 |
3 | A-DA40 | ラウンドダイニングチェア | チェア | 28000 |
4 | O-XX100 | ナチュラルオフィス | チェア | 13800 |
5 | R-D400 | ラウンドダイニングテーブル | テーブル | 128000 |
6 | R7000 | ウッドキャビネット | その他 | 32000 |
7 | B-200 | リネンベッド | ベッド | 184500 |
8 | B-250 | ホワイトダブルベッド | ベッド | 324850 |
9 | W-80 | ワーキングチェア | チェア | 45000 |
10 | EG-10X | エルゴノミクスデスク | テーブル | 88500 |
id | category |
---|---|
1 | チェア |
2 | ベッド |
上記のテーブルが存在した場合に、以下のSQLを実行します。
SELECT * FROM products WHERE EXISTS (SELECT id FROM sale WHERE products.category = sale.category)
または
SELECT * FROM products AS P WHERE EXISTS (SELECT id FROM sale WHERE P.category = category)
SELECT id FROM sale WHERE P.category = category
のサブクエリでは、
メインのクエリの行のcategory(P.category)に一致するcategoryがsaleテーブルに存在するかを検索しています。
メインのクエリのcategoryに一致するcategoryがsaleテーブルに存在すれば、saleテーブルの該当するcategoryの行が返り existsがtrueになります。
クエリ全体ではproductsテーブルのcategoryがsaleテーブルのcategoryに含まれているレコードを返します。
id | model | name | category | price |
---|---|---|---|---|
1 | C-XM01 | モーダンチェア | チェア | 56000 |
3 | A-DA40 | ラウンドダイニングチェア | チェア | 28000 |
4 | O-XX100 | ナチュラルオフィス | チェア | 13800 |
7 | B-200 | リネンベッド | ベッド | 184500 |
8 | B-250 | ホワイトダブルベッド | ベッド | 324850 |
9 | W-80 | ワーキングチェア | チェア | 45000 |
SELECT * FROM products WHERE category IN (SELECT category FROM sale)
SELECT * FROM products WHERE category='チェア' OR category='ベッド'
id | model | name | category | price |
---|---|---|---|---|
1 | C-XM01 | モーダンチェア | チェア | 56000 |
2 | X-XD05 | ラージデスク | テーブル | 87000 |
3 | A-DA40 | ラウンドダイニングチェア | チェア | 28000 |
4 | O-XX100 | ナチュラルオフィス | チェア | 13800 |
5 | R-D400 | ラウンドダイニングテーブル | テーブル | 128000 |
6 | R7000 | ウッドキャビネット | その他 | 32000 |
7 | B-200 | リネンベッド | ベッド | 184500 |
8 | B-250 | ホワイトダブルベッド | ベッド | 324850 |
9 | W-80 | ワーキングチェア | チェア | 45000 |
10 | EG-10X | エルゴノミクスデスク | テーブル | 88500 |
id | category |
---|---|
1 | チェア |
2 | ベッド |
上記のテーブルが存在した場合に、以下のSQLを実行します。
SELECT * FROM ProductsB
WHERE NOT EXISTS (SELECT id FROM sale WHERE ProductsB.category = sale.category)
EXISTS
が NOT EXISTS
となっています。productsテーブルのcategoryがsaleテーブルのcategoryに含まれていないレコードを返します。
以下の結果が得られます。
id | model | name | category | price |
---|---|---|---|---|
2 | X-XD05 | ラージデスク | テーブル | 87000 |
5 | R-D400 | ラウンドダイニングテーブル | テーブル | 128000 |
6 | R7000 | ウッドキャビネット | その他 | 32000 |
10 | EG-10X | エルゴノミクスデスク | テーブル | 88500 |
――婚活パーティー会場。
白いテーブルクロスにオレンジジュースが映り込み、照明がゆらめく。向かいに座る田中沙織は、
紺のワンピースに身を包み、けれど指先の落ち着かない様子がどこか初々しかった。
「趣味は何をされていますか?」
彼女が聞く。
「読書と……少しだけデータベースを触っています」
僕が答えると、沙織はぱっと顔を明るくした。
「データって聞くとワクワクします。私、Excelが大好きで。毎晩ピボットテーブル眺めてるんです」
まさかの Excel トークに胸が高鳴る。
「COUNTIF で条件に合う行がいくつあるか数えるのが楽しくて。
けど、会社の人が『SQL なら EXISTS が速い』って言っていて――正直よく分からなくて……」
そう言って、沙織は眉を下げた。指でテーブルクロスを撫でて小さな皺を作る。
「EXISTS ですね。COUNTIF は全部数えてから “いくつある” を返しますが、EXISTS は“1行目が見つかった瞬間” に
『ある!』って判定して終わるんです。だから大量データのときは速いですし、“存在しているかどうか” をはっきり書けるので読みやすいんですよ」
僕は紙ナプキンの裏にペンで小さく
SELECT 1
FROM Participants p
WHERE p.Preference = :herPreference
AND p.UserID = :myID
と書き、〇で囲った。
「このサブクエリを EXISTS に渡すと、条件を満たす行が1つでも見つかった時点で TRUE を返す。
婚活も同じで、理想の人が“ひとりでも”いれば次のステップに進める――そんな感じです」
沙織は驚いたように目を丸くした。
「全部数えなくてもいいんですね……それって、時間だけじゃなくて、ドキドキも減らせるかも。理想通りの人がレコードの海に埋もれてても、早く見つけられるってわけですね?」
「そうです。COUNTIF は“総人数”を意識しますが、EXISTS は“出会いがあるかどうか”だけを見てくれる」
沙織はしばらくナプキンの文字を眺め、ふっと笑った。頬がわずかに紅く染まる。
「じゃあ……今日の参加者テーブルで、あなたは私の EXISTS を TRUE にしてくれるでしょうか?」
僕はペンを置き、そっと彼女の目を見た。
「WHERE 句はまだ書きかけだけど――少なくとも、第一引数に“話が合うこと”は入っています」
その瞬間、パーティー終了を告げるベルが鳴った。
「本当は、帰り際にサブクエリを実行する予定だったんですけど」
沙織は立ち上がりながら小声でつぶやく。
「大丈夫。拾えました。EXISTS はもう TRUE です」
出口で渡されたアンケート用紙――そこにはチェックボックスが並んでいる。僕らは同時に“マッチング希望”をマークし、笑い合った。
まるでデータベースが高速で返した結果のように、僕らの気持ちは瞬時に合致していた。
COUNTIF が数える前に、心の EXISTS が先に TRUE を返したのだ。