ITの教科書検索
入門読了 約10分

SQLのINとBETWEENとは ― 使い方とNOT IN

SQLのINは値の一覧のどれかに合う行を、BETWEENは下限以上・上限以下の行を選びます。両端の扱い、日付の落とし穴、NOT INの一覧にNULLがあると0行になる理由が分かります。

目次
  1. SQLのINとBETWEENとは
  2. ORとANDでの書き換え
  3. 条件を選んで残る行を確かめる
  4. BETWEENは両端を含む
  5. 日付と文字列のBETWEEN
  6. NOT INとNOT BETWEEN
  7. NOT INの一覧にNULLがあるとき
  8. INにサブクエリを書く
  9. 練習問題

SQLのINとBETWEENとは、WHERE句で値の候補や範囲を指定する述語

SQLのINは、列の値が一覧に並べた値のどれかに等しい行を選ぶ述語(条件を表す語)です。BETWEENは、列の値が下限以上かつ上限以下の範囲に入る行を選びます。

どちらもSELECT文のWHERE句で、価格が500円・1000円・3000円のどれかの商品や、1000円から3000円の商品を選ぶときに使います。LIKEは文字列の一部で行を選びますが、INとBETWEENは値の候補や大小の範囲で行を選びます。

SELECT 商品名 FROM 商品
WHERE 価格 IN (500, 1000, 3000);        -- 3つの価格のどれか

SELECT 商品名 FROM 商品
WHERE 価格 BETWEEN 1000 AND 3000;       -- 1000以上3000以下

次の商品の表を例にします。上の1つ目の文はUSBケーブル・マウス・Webカメラを、2つ目の文はマウスからWebカメラまでの4行を返します。

例に使う商品の表
商品名価格
USBケーブル500
マウス1000
スピーカー2000
キーボード2500
Webカメラ3000
ヘッドセット4800

INはORの連続、BETWEENは>=と<=のANDと同じ

INは=をORでつないだ条件の略記で、BETWEENは>=と<=をANDでつないだ条件の略記です。PostgreSQLの文書も、INを=のOR連結の略記として説明し、BETWEENは a >= x AND a <= y と同じだと説明しています。

IN・BETWEENと、同じ意味になる比較演算子の書き方
述語同じ意味の書き方残る商品
価格 IN (500, 1000, 3000)価格 = 500 OR 価格 = 1000 OR 価格 = 3000USBケーブル・マウス・Webカメラ
価格 BETWEEN 1000 AND 3000価格 >= 1000 AND 価格 <= 3000マウス・スピーカー・キーボード・Webカメラ
価格 NOT IN (500, 1000)価格 <> 500 AND 価格 <> 1000スピーカー・キーボード・Webカメラ・ヘッドセット
価格 NOT BETWEEN 1000 AND 3000価格 < 1000 OR 価格 > 3000USBケーブル・ヘッドセット

どちらの書き方でも、残る行は同じです。PostgreSQLで実行すると、表の4組はどれも同じ行を返しました。候補が多いときはINのほうが短く書け、列名を書き間違える箇所も減ります。

MySQLの文書は、INの一覧に引用符付きの値と数値を混ぜないように注意を促しています。文字列と数値では比べ方の決まりが違い、結果がそろわないことがあるためです。一覧の値は、列と同じ型にそろえて書きます。

条件を選んで、表のどの行が残るかを確かめる

次の図では、最初に示した商品の表にINやBETWEENの条件を試せます。条件を選ぶと、ORやANDに書き換えた式の各行の判定と、結果に残る行が切り替わります。結果は、PostgreSQLで実際に実行して確かめたものです。

WHERE の条件
SELECT 商品名 FROM 商品
WHERE 価格 IN (500, 1000, 3000);
同じ意味の書き方価格 = 500 OR 価格 = 1000 OR 価格 = 3000
  1. USBケーブル500TRUE OR FALSE OR FALSE → TRUE残る
  2. マウス1000FALSE OR TRUE OR FALSE → TRUE残る
  3. スピーカー2000FALSE OR FALSE OR FALSE → FALSE除かれる
  4. キーボード2500FALSE OR FALSE OR FALSE → FALSE除かれる
  5. Webカメラ3000FALSE OR FALSE OR TRUE → TRUE残る
  6. ヘッドセット4800FALSE OR FALSE OR FALSE → FALSE除かれる
結果に残る行:USBケーブル・マウス・Webカメラ(3行)
一覧のどれか1つと等しければTRUEです。=をORでつないだ書き方と、残る行は同じです。

BETWEEN 1000 AND 3000 と、>と<で書いた条件を比べると、両端の扱いの違いが分かります。NOT INの一覧にNULLを足すと、それまで残っていた4行が全部消えます。

BETWEENは両端を含み、小さい値を先に書く

BETWEEN 1000 AND 3000 は、1000ちょうどと3000ちょうどの行も選びます。日本語に直すと、1000円以上3000円以下です。PostgreSQLの文書も、BETWEENは範囲の端の値を範囲に含めると説明しています。

残る行除かれる行価格 BETWEEN 1000 AND 3000含む含む50010002000250030004800価格 > 1000 AND 価格 < 3000含まない含まない50010002000250030004800価格 BETWEEN1000 AND 30005001000含む200025003000含む4800価格 > 1000 AND価格 < 30005001000含まない200025003000含まない4800残る行除かれる行
BETWEENは、範囲の端にちょうど乗る1000と3000も残します。>と<で書くと両端は除かれ、残るのは2000と2500だけです。

端を含めたくないときは、BETWEENを使わずに>と<で書きます。価格 > 1000 AND 価格 < 3000 なら、1000円より高く3000円より安い行だけが残ります。

上限を先に書くと、エラーにならずに0行になる

BETWEENは、ANDの左に下限を、右に上限を書きます。逆に価格 BETWEEN 3000 AND 1000 と書くと、3000以上かつ1000以下の値を探すことになります。そのような値は無いので、エラーは出ず、結果は0行になります。

PostgreSQLの文書でも、MySQLの文書でも、2 BETWEEN 3 AND 1 の結果は偽です。PostgreSQLには、2つの値を小さい順に並べ替えてから比べる BETWEEN SYMMETRIC もあります。MySQLの文書のBETWEENの説明には、この書き方は出てきません。

日付や文字列でBETWEENを使うときの注意

日時の列に日付だけで上限を書くと、最終日の0時より後が漏れる

10月の注文を探すつもりで、日時の列に次の条件を書いたとします。PostgreSQLで6件の注文の表に実行すると、10月31日の14時20分の注文が結果に入りませんでした。

WHERE 注文日時 BETWEEN '2026-10-01' AND '2026-10-31'
-- 10/31 0:00 までしか入らない(10/31 14:20 の注文は外れる)

WHERE 注文日時 >= '2026-10-01' AND 注文日時 < '2026-11-01'
-- 10/31 の全ての時刻が入る

日時の列と比べるとき、日付だけの '2026-10-31' は10月31日の0時0分として扱われます。BETWEENの範囲はその時刻で終わるので、同じ日の0時より後の注文は外れます。

残る行除かれる行10/31 0:0014:2011/01 0:00注文日時 BETWEEN '2026-10-01' AND '2026-10-31'← 10/01から上限100410051006注文日時 >= '2026-10-01' AND 注文日時 < '2026-11-01'含まない10041005100610/30 0:0010/31 0:0014:2011/01 0:00BETWEEN上限 10-31100410051006>= と <11-01 未満100410051006残る行除かれる行
日時の列と比べると、'2026-10-31' は10月31日の0時を表します。BETWEENの範囲はそこで終わるので、14時20分の注文1005は外れます。

日時の列で日の範囲を選ぶときは、翌日の0時を<で上限にします。この書き方なら、最終日の何時の注文でも範囲に入ります。列が時刻を持たない日付の型なら、BETWEEN '2026-10-01' AND '2026-10-31' で31日の行も入ります。

MySQLの文書も、日付や時刻にBETWEENを使うときは、CAST()で値の型をそろえるように勧めています。たとえば日時の列を2つの日付と比べるなら、日付の側を日時の型に直します。

文字列のBETWEENは、文字の並び順で範囲を決める

BETWEENの中身は大小の比較なので、大小を比べられる文字列にも使えます。文字列の大小は、辞書のように先頭の文字から順に比べて決まります。

WHERE 名前 BETWEEN 'A' AND 'C'      -- Alice・Bob・C(Carolは入らない)
WHERE 名前 >= 'A' AND 名前 < 'D'    -- Alice・Bob・C・Carol

Carolは、Cの1文字より後ろに並びます。そのため、上限を 'C' にするとCarolは範囲から外れます。Cで始まる名前まで含めたいときは、次の文字のDを<で上限にします。

大文字と小文字のどちらを先に並べるかは、照合順序によって変わります。照合順序は文字の比べ方の決まりで、製品と設定ごとに違います。LIKEで大文字と小文字を区別するかどうかも照合順序で決まります。詳しくはLIKEの記事で説明しています。

NOT INとNOT BETWEENは、条件に合わない行を選ぶ

NOT INは、一覧のどの値とも等しくない行を選びます。NOT BETWEENは、範囲の外にある行を選びます。どちらも、INやBETWEENの結果を逆にした条件です。

WHERE 価格 NOT IN (500, 1000)           -- スピーカー・キーボード・Webカメラ・ヘッドセット
WHERE 価格 NOT BETWEEN 1000 AND 3000    -- USBケーブル・ヘッドセット

NOT BETWEEN 1000 AND 3000 は、価格 < 1000 OR 価格 > 3000 と同じです。BETWEENが両端を含むので、NOT BETWEENでは1000ちょうどと3000ちょうどの行が除かれます。NOT INは、<>をANDでつないだ条件になります。

否定の条件では、列の値がNULLの行も選ばれません。理由と、NULLの行も残す書き方はSQLのNULLの記事で説明しています。

NOT INの一覧にNULLがあると、1行も残らない

NOT INの一覧にNULLが1つでも入っていると、結果は0行になります。価格 NOT IN (500, 1000, NULL) は、次のようにANDでつないだ条件と同じです。

価格 <> 500 AND 価格 <> 1000 AND 価格 <> NULL

価格が2000のスピーカーでは、最初の2つはTRUEです。しかし最後の 2000 <> NULL は、NULLとの比較なのでUNKNOWNになります。TRUEとUNKNOWNをANDでつなぐとUNKNOWNになり、WHERE句はこの行を残しません。

500や1000の行は、最初の比較がFALSEなので、AND全体もFALSEです。こうして全ての行がFALSEかUNKNOWNになります。UNKNOWNとANDの組み合わせの決まりは、SQLのNULLの記事の3値論理の表で確かめられます。

一方、INの一覧のNULLは結果を変えません。価格 IN (500, 1000, NULL) は、500と1000の行をTRUEにします。ほかの行はUNKNOWNになりますが、FALSEのときと同じく結果から外れるからです。

PostgreSQLとMySQLの文書は、どちらもこの扱いを説明しています。一致する値が無く、一覧にNULLがあるとき、INの結果はNULLになります。一覧を手で書くならNULLを入れなければ済みますが、サブクエリ(SQL文の中に書いたSELECT文)で一覧を作るときは、NULLの混入に気づきにくくなります。

INの右側には、サブクエリの結果も書ける

INの右側には、値を並べる代わりにSELECT文を書けます。内側のSELECT文が返した1列の値が、そのまま一覧として使われます。

SELECT 商品名 FROM 商品
WHERE 商品名 IN (
  SELECT 商品名 FROM 注文明細   -- マウス・Webカメラ・マウス
);                              -- 結果:マウス・Webカメラ

注文明細にマウスが2回出ても、商品の表のマウスは1行として1回だけ残ります。内側の結果にNULLが混じると、NOT INでは前の節と同じことが起きます。NOT EXISTSを使って避ける方法を、サブクエリの記事で説明しています。

INやBETWEENの条件の列にB-treeのインデックスがあれば、索引で探せる場合があります。PostgreSQLの文書は、BETWEENとINを、B-treeの索引で探せる書き方の例に挙げています。索引の仕組みはインデックスの記事で説明しています。

参考にした資料

練習問題(全5問)

Q1価格 BETWEEN 1000 AND 3000 と同じ条件はどれ?
Q2価格 BETWEEN 3000 AND 1000 を実行した。結果はどうなる?
Q3注文日時が日時の型の列に、WHERE 注文日時 BETWEEN '2026-⁠10-⁠01' AND '2026-⁠10-⁠31' を実行した。結果に入らない注文はどれ?
Q4価格 NOT IN (500, 1000, NULL) の結果はどうなる?
Q5商品名 IN ('マウス', 'キーボード') と同じ条件はどれ?

選んでから「採点する」を押すと、解説つきで答え合わせができます。

関連記事

おすすめの本 PR

セキュリティとデータベースは、基本情報技術者試験の対策本でまとめて学べます。

目的別の本の選び方を見る

データベースの記事を続けて読む

データベース 全36本中10本目