0Pricing
Coding Interview Prep · レッスン

BETWEEN、IN、境界値の扱い

境界値のエッジケースと、BETWEENによる端点の扱いを学びます。

「BETWEEN、IN、境界値の扱い」はCoddyKit上の無料Coding Interview Prepレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはCoding Interview Prep学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Coding Interview Prepコースには全4レッスンが含まれています。

境界値で候補者が減点される理由

範囲フィルターや集合フィルターは簡単に見えるため、面接官は境界値のケースを問題にします。BETWEENは両端点を含み、INには気づきにくいNULLの落とし穴があり、日付範囲ではオフバイワンエラーによってレポートがひそかに壊れることがあります。

このレッスンでは、BETWEENが端点をどのように扱うか、連鎖したORよりINが適している場面、そしてプロフェッショナルが日付に使う半開区間のパターンを正確に学びます。

BETWEENは両端を含む

col BETWEEN a AND bはcol >= a AND col <= bの省略形です。両方の端点が含まれます。

したがって、price BETWEEN 10 AND 20は、価格がちょうど10またはちょうど20の行も、その間のすべての行も返します。面接で最もよくある誤答は、上限は含まれないと言うことです。

SELECT *
FROM products
WHERE price BETWEEN 10 AND 20;
-- equivalent to: price >= 10 AND price <= 20

引数の順序が重要

BETWEENでは、下限の値を先に指定する必要があります。col BETWEEN 20 AND 10はcol >= 20 AND col <= 10に展開されます。これは真になり得ないため、エラーではなく0行を返します。

これは面接でよく出る落とし穴です。クエリは問題なく実行されて何も返さないため、候補者はデータが空だと思い込んでしまいます。必ず小さいほうの境界値を先に置いてください。

SELECT *
FROM products
WHERE price BETWEEN 20 AND 10;
-- returns NOTHING, not an error

日付範囲のオフバイワン

1月全体を求められると、多くの候補者はorder_date BETWEEN '2024-01-01' AND '2024-01-31'と書きます。order_dateがタイムスタンプの場合、2024-01-31は2024-01-31 00:00:00を意味するため、これは31日の午前0時以降のすべてを除外します。

1月31日の午後2時の注文は除外されます。純粋なDATE型の列なら機能しますが、型を決めつけることはできません。

SELECT *
FROM orders
WHERE order_date BETWEEN '2024-01-01' AND '2024-01-31';
-- silently excludes Jan 31 afternoon if order_date is a timestamp

半開区間による修正

日付に対するプロフェッショナルなパターンは半開区間です。開始日時以上、次の期間の開始日時未満とします。これはDATEとTIMESTAMPの両方で正しく機能し、列の時刻精度を知る必要もありません。

上限が1月の最終日ではなく、2月の1日目になっていることに注目してください。これにより、1月のすべての時点を含められます。

SELECT *
FROM orders
WHERE order_date >= '2024-01-01'
  AND order_date <  '2024-02-01';

NOT BETWEEN

col NOT BETWEEN a AND bはcol < a OR col > bに展開されます。両端点と、その間にあるすべての値を除外します。

注意が必要なのは、colがNULLの場合、NOT BETWEENの評価結果がUNKNOWNになることです。そのため、通常のBETWEENと同じようにNULLの行は除外されます。NULLはどちらの方向の範囲判定も満たしません。

SELECT *
FROM products
WHERE price NOT BETWEEN 10 AND 20;
-- price < 10 OR price > 20

集合のメンバーシップとしてのIN

col IN (a, b, c)はcol = a OR col = b OR col = cの省略形です。小さく固定された集合に含まれるかどうかを調べる、すっきりした方法です。

ORを連鎖させるより読みやすく、集合全体の判定が1つの述語になるため、優先順位に関する括弧の問題も完全に避けられます。

SELECT *
FROM orders
WHERE status IN ('pending', 'shipped', 'delivered');

NOT INとNULLの落とし穴

これはINに関する質問の中で最も恐れられているものです。NOT INの背後にあるリスト(またはサブクエリ)にNULLが1つでも含まれていると、述語全体の評価結果がUNKNOWNになり、0行を返すことがあります。

理由は、x NOT IN (1, NULL)がx <> 1 AND x <> NULLになるためです。x <> NULLは決して真にならず、UNKNOWNになります。そのため、全体のANDが真になることはありません。

SELECT *
FROM employees
WHERE manager_id NOT IN (SELECT id FROM managers);
-- returns NOTHING if any managers.id is NULL

NOT INの修正

NOT INのNULLの落とし穴に対する、堅牢な修正方法は2つあります。

  • WHERE id IS NOT NULLを使って、サブクエリからNULLを除外します
  • よりよい方法として、NULLを設計上正しく扱えるNOT EXISTSに書き換えます

面接官がNOT EXISTSをシニア向けの答えと考えるのは、落とし穴を完全に回避でき、多くの場合に実行計画も改善されるからです。

SELECT e.*
FROM employees e
WHERE NOT EXISTS (
  SELECT 1 FROM managers m WHERE m.id = e.manager_id
);

サブクエリを使ったIN

INには、1列を返すサブクエリを指定できます。WHERE customer_id IN (SELECT customer_id FROM vip)とすると、顧客がVIP集合に含まれる行を残せます。

通常のIN(NOT INではないもの)は、サブクエリにNULLがあっても安全です。リスト内のNULLは単に一致しませんが、一致する行に悪影響を与えることはありません。落とし穴があるのはNOT INに限られます。

SELECT *
FROM orders
WHERE customer_id IN (SELECT customer_id FROM vip_customers);

行コンストラクタによる複数列IN

よくある追加質問に、複数の列を一度に照合するにはどうすればよいかというものがあります。行コンストラクタを使ってタプルをINに渡します。列を位置に基づいて比較でき、OR (a = .. AND b = ..)を連ねるよりもはるかにすっきりします。

  • 読みやすく、許可リストが長くなっても対応しやすい方法です。
  • 各タプルでは、列を同じ順序で指定する必要があります。
SELECT *
FROM orders
WHERE (customer_id, status) IN ((101, 'paid'), (102, 'shipped'));

クイックチェック

BETWEENが端点をどのように扱うか思い出してください。

まとめ

重要なポイント:

  • BETWEEN a AND bは両方の端点を含みます。下限を先に指定しないと0行になります
  • タイムスタンプの範囲には半開区間を使います:>= start AND < next_period
  • INは集合のメンバーシップを明確に表し、NULLに対して安全です
  • リストにNULLが1つでもあるNOT INは何も返さないため、NOT EXISTSに書き換えます

繰り返し現れるテーマは、フィルターが問題なく実行されても、ひそかに間違った行を返すことがあるという点です。

よくある質問

「BETWEEN、IN、境界値の扱い」レッスンは無料ですか?

はい。「BETWEEN、IN、境界値の扱い」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Coding Interview Prepコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Coding Interview Prepコースには全4レッスンが含まれています。

「BETWEEN、IN、境界値の扱い」で何を学びますか?

境界値のエッジケースと、BETWEENによる端点の扱いを学びます。 ブラウザで直接実行するハンズオンコードでCoding Interview Prepを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Coding Interview Prepを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのCoding Interview Prepは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「BETWEEN、IN、境界値の扱い」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このCoding Interview Prepレッスンでコードを書いて実行できますか?

はい。すべてのCoding Interview Prepレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. AND/ORの優先順位と括弧の付け方
  2. BETWEEN、IN、境界値の扱い
  3. LIKE、ワイルドカード、エスケープ
  4. 計算値でフィルタリングする
← Coding Interview Prepに戻る