レコードが存在するかの条件判定 EXISTS 演算子の利用

SQLで条件にマッチするレコードが存在するか判定する場合のSQLについて紹介します。

概要

レコードが存在するかを条件にする場合は、EXISTS演算子を用います。

書式

where節で以下の書式を利用します。

EXISTS (サブクエリ)

レコードが存在しないことを条件にする場合は not exists が利用できます。

NOT EXISTS (サブクエリ)

書式例

SELECT * FROM products WHERE EXISTS (SELECT id FROM sale)

実行例1:動作確認の例

products
idmodelnamecategoryprice
1C-XM01モーダンチェアチェア56000
2X-XD05ラージデスクテーブル87000
3A-DA40ラウンドダイニングチェアチェア28000

上記のテーブルが存在した場合

SELECT * FROM products WHERE EXISTS (SELECT TOP(0) * FROM products)

のSQLは何も結果を返しません。"select top(0) * from products"のSQLはレコードを全く返さないため、existsは常にfalseとなりすべてのレコードで条件にマッチしないため何も結果を返さない動作となります。

結果

idmodelnamecategoryprice

実行例2:動作確認の例

products
idmodelnamecategoryprice
1C-XM01モーダンチェアチェア56000
2X-XD05ラージデスクテーブル87000
3A-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 '')

結果

idmodelnamecategoryprice
1C-XM01モーダンチェアチェア56000
2X-XD05ラージデスクテーブル87000
3A-DA40ラウンドダイニングチェアチェア28000

実行例3:別のテーブルに存在する値を持つ行のみを取得

products
idmodelnamecategoryprice
1C-XM01モーダンチェアチェア56000
2X-XD05ラージデスクテーブル87000
3A-DA40ラウンドダイニングチェアチェア28000
4O-XX100ナチュラルオフィスチェア13800
5R-D400ラウンドダイニングテーブルテーブル128000
6R7000ウッドキャビネットその他32000
7B-200リネンベッドベッド184500
8B-250ホワイトダブルベッドベッド324850
9W-80ワーキングチェアチェア45000
10EG-10Xエルゴノミクスデスクテーブル88500
sale
idcategory
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に含まれているレコードを返します。

結果

idmodelnamecategoryprice
1C-XM01モーダンチェアチェア56000
3A-DA40ラウンドダイニングチェアチェア28000
4O-XX100ナチュラルオフィスチェア13800
7B-200リネンベッドベッド184500
8B-250ホワイトダブルベッドベッド324850
9W-80ワーキングチェアチェア45000
補足
上記のクエリは以下のクエリと同じ結果を返します。
SELECT * FROM products WHERE category IN (SELECT category FROM sale)
SELECT * FROM products WHERE category='チェア' OR category='ベッド'

実行例4 : not exists の例

products
idmodelnamecategoryprice
1C-XM01モーダンチェアチェア56000
2X-XD05ラージデスクテーブル87000
3A-DA40ラウンドダイニングチェアチェア28000
4O-XX100ナチュラルオフィスチェア13800
5R-D400ラウンドダイニングテーブルテーブル128000
6R7000ウッドキャビネットその他32000
7B-200リネンベッドベッド184500
8B-250ホワイトダブルベッドベッド324850
9W-80ワーキングチェアチェア45000
10EG-10Xエルゴノミクスデスクテーブル88500
sale
idcategory
1チェア
2ベッド

上記のテーブルが存在した場合に、以下のSQLを実行します。

SELECT * FROM ProductsB 
  WHERE NOT EXISTS (SELECT id FROM sale WHERE ProductsB.category = sale.category)

解説

例3と同じですが EXISTSNOT EXISTS となっています。

productsテーブルのcategoryがsaleテーブルのcategoryに含まれていないレコードを返します。

結果

以下の結果が得られます。

idmodelnamecategoryprice
2X-XD05ラージデスクテーブル87000
5R-D400ラウンドダイニングテーブルテーブル128000
6R7000ウッドキャビネットその他32000
10EG-10Xエルゴノミクスデスクテーブル88500


応用例
NOT EXISTSを利用する例として、グループごとに値の最大値のレコードを求める場合に利用します。 詳細はこちらの記事を参照してください。

A.W.S (Another World Story)

レコードが存在するかの条件判定 EXISTS 演算子の利用:画像1

――婚活パーティー会場。
白いテーブルクロスにオレンジジュースが映り込み、照明がゆらめく。向かいに座る田中沙織は、 紺のワンピースに身を包み、けれど指先の落ち着かない様子がどこか初々しかった。

「趣味は何をされていますか?」 彼女が聞く。

「読書と……少しだけデータベースを触っています」
僕が答えると、沙織はぱっと顔を明るくした。

「データって聞くとワクワクします。私、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 を返したのだ。


このページのキーワード
  • SQL レコード 存在 判定
AuthorPortraitAlt
著者
iPentec.com の代表。ハードウェア、サーバー投資、管理などを担当。
Office 365やデータベースの記事なども担当。
作成日: 2014-08-12
Copyright © 1995–2025 iPentec all rights reserverd.