1. はじめに:WHERE句は「SQL品質の半分」を決める
OracleのSQLで最も多く書かれる句が WHERE
です。
単なる条件指定に見えて、パフォーマンス・正確性・保守性を大きく左右します。
本記事では、基本構文から“現場で使える条件指定のテクニック”まで、
体系的に理解できるようにまとめました。
2. WHERE句の基本構文と評価順序
1 2 3 4 |
SELECT 列名 FROM テーブル名 WHERE 条件式; |
Oracleのクエリ処理順序では
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
の順に評価されます。
つまり、WHERE句は最初の絞り込み段階で最も重要です。
3. AND/OR の正しい使い方と注意点
■ 基本構文
1 2 3 |
SELECT * FROM SALES WHERE AREA = 'TOKYO' AND AMOUNT > 100000; |
👉 AND は「すべての条件を満たす」、
OR は「いずれかを満たす」。
■ ORを多用すると遅くなる理由
ORを多用するとインデックスが効きにくくなります。
パフォーマンスを上げるなら、以下のように書き換え可能です。
1 2 3 4 5 6 |
-- 悪い例 WHERE AREA = 'TOKYO' OR AREA = 'OSAKA'; -- 良い例 WHERE AREA IN ('TOKYO', 'OSAKA'); |
4. IN/EXISTS の使い分け
■ IN句:小規模データに最適
1 2 3 |
SELECT * FROM EMP WHERE DEPTNO IN (SELECT DEPTNO FROM DEPT WHERE LOC = 'TOKYO'); |
サブクエリが少数(100件未満)なら IN
が高速です。
■ EXISTS句:大規模データ向け
1 2 3 4 5 6 7 |
SELECT * FROM EMP e WHERE EXISTS ( SELECT 1 FROM DEPT d WHERE d.DEPTNO = e.DEPTNO AND d.LOC = 'TOKYO' ); |
EXISTS
はマッチした瞬間に評価を終了するため、
大規模サブクエリでは IN
より効率的です。
5. NULL比較の落とし穴と対策
Oracleでは NULL
は値が「存在しない」状態であり、
比較演算子(=
や !=
)では一致しません。
■ NG例(常にFALSE)
1 2 |
WHERE COLUMN_A = NULL |
■ 正しい書き方
1 2 3 |
WHERE COLUMN_A IS NULL WHERE COLUMN_A IS NOT NULL |
■ NVL関数でNULLを明示的に処理
1 2 |
WHERE NVL(DELETE_FLG, 'N') = 'N' |
👉 削除フラグがNULLの行も“未削除”として扱いたいときに便利です。
6. BETWEEN・LIKE の最適な使い方
■ 範囲検索(BETWEEN)
1 2 3 |
WHERE ORDER_DATE BETWEEN TO_DATE('2025-10-01', 'YYYY-MM-DD') AND TO_DATE('2025-10-31', 'YYYY-MM-DD'); |
BETWEEN
は 両端を含む(Inclusive) ので注意。
上記例では 10/31 23:59:59 まで含まれます。
■ 部分一致検索(LIKE)
1 2 |
WHERE CUSTOMER_NAME LIKE '田中%'; |
%
:任意の文字列_
:任意の1文字
■ LIKE+インデックス活用のコツ
前方一致(LIKE 'A%'
)はインデックス有効。
しかし後方一致(LIKE '%A'
)は全件スキャンになるため注意。
改善策として INSTR
関数を使う方法もあります👇
1 2 |
WHERE INSTR(CUSTOMER_NAME, '田中') > 0; |
7. CASE式とWHERE句の組み合わせ応用
条件が動的に変わる場合は、CASE式を使って柔軟に制御可能です。
1 2 3 4 5 6 7 |
SELECT * FROM SALES WHERE CASE WHEN :MODE = 'A' THEN STATUS WHEN :MODE = 'B' THEN TYPE END = 'ACTIVE'; |
👉 業務システムで検索条件を可変にしたい場合に便利です。
8. 実務で役立つWHERE句テクニック集
シーン | SQL例 | ポイント |
---|---|---|
NULLを含む比較 | WHERE NVL(flag, 'N') = 'N' | 削除フラグや状態判定で便利 |
曜日判定 | WHERE TO_CHAR(SYSDATE, 'DY') = '月' | 営業日抽出に応用 |
日付範囲 | WHERE TRUNC(order_date) BETWEEN ... | 時刻部分を除いて比較 |
部分一致 | WHERE INSTR(name, '株式会社') > 0 | LIKEより高速な場合あり |
指定除外 | WHERE code NOT IN ('A','B','C') | INの反転条件 |
優先条件 | WHERE (status = '1' AND flag = 'N') OR priority = 'Y' | 括弧で評価順を明確化 |
9. パフォーマンス改善のヒント
問題 | 対策 |
---|---|
複雑なOR条件で遅い | UNIONまたはINに書き換える |
WHEREで関数使用が多い | 関数索引(Function-Based Index)を検討 |
NULL比較でINDEX無効化 | NVLで明示的に比較値を補完 |
フラグ列が多い | ビットマスク管理 or ENUMテーブル化を検討 |
10. まとめ:WHERE句を制す者がOracleを制す
分類 | キーワード | 特徴 |
---|---|---|
論理条件 | AND/OR/IN/EXISTS | 検索効率の基本 |
NULL処理 | IS NULL/NVL | 正確な条件分岐 |
範囲・曖昧 | BETWEEN/LIKE/INSTR | 現場で頻出 |
最適化 | 関数索引/UNION化 | パフォーマンス改善 |
OracleのWHERE句は、「ただ条件を絞る句」ではなく、
SQL全体の性能と信頼性を決定づける中核ロジックです。
構文の正確さと実行計画の理解、両方を意識して使いこなしましょう。
コメント