「年齢が20歳以上で、女性だけを表示したい」
「キャンペーン中または割引中の商品を検索したい」
──そんな要望を実現するために必要なのが、SQLの複数条件指定です。
SQLでは、WHERE句の中にAND(かつ)・OR(または)・NOT(ではない)といった論理演算子を組み合わせることで、複雑な条件も簡単に表現できます。
この記事では、SQLで複数条件を指定する方法を初心者にもわかりやすく解説し、実際の仕事でよく使う例も詳しく紹介します。
複数条件を使うための基本
論理演算子とは?
論理演算子は、複数の条件を組み合わせるときに使う言葉です。
日常会話でも「AかつB」「AまたはB」「Aではない」という表現を使いますが、SQLでも同じように考えられます。
基本的な構文
SELECT * FROM テーブル名
WHERE 条件1 AND 条件2;
3つの論理演算子
演算子 | 意味 | 日常の言葉 | 例 |
---|---|---|---|
AND | かつ、そして | 「〜で、なおかつ〜」 | age >= 20 AND gender = '女性' |
OR | または | 「〜か、または〜」 | status = '完了' OR status = '処理中' |
NOT | ではない | 「〜以外」 | NOT status = 'キャンセル' |
具体例で理解しよう
1つの条件だけの場合
SELECT * FROM users WHERE age >= 20;
→ 20歳以上の人だけ
2つの条件をANDで組み合わせた場合
SELECT * FROM users WHERE age >= 20 AND gender = '女性';
→ 20歳以上で、かつ女性の人だけ
2つの条件をORで組み合わせた場合
SELECT * FROM users WHERE age >= 60 OR age <= 18;
→ 60歳以上または18歳以下の人
ANDの使い方:「かつ」の条件
ANDは「すべての条件を満たす」ときに使います。
基本的な使い方
-- 年齢が20歳以上で、かつ東京都に住んでいる人
SELECT * FROM users
WHERE age >= 20 AND address LIKE '%東京都%';
-- 価格が1000円以上で、かつ在庫が10個以上の商品
SELECT * FROM products
WHERE price >= 1000 AND stock >= 10;
3つ以上の条件を組み合わせる
-- 年齢が20歳以上で、女性で、東京都に住んでいる人
SELECT * FROM users
WHERE age >= 20
AND gender = '女性'
AND address LIKE '%東京都%';
-- 価格が500円以上1500円以下で、在庫があり、評価が4以上の商品
SELECT * FROM products
WHERE price >= 500
AND price <= 1500
AND stock > 0
AND rating >= 4;
実際の業務での使用例
顧客管理システム
-- アクティブな優良顧客を検索
-- (最終ログインが30日以内で、購入金額が10万円以上)
SELECT customer_name, last_login, total_purchase
FROM customers
WHERE last_login >= '2025-05-04' -- 30日前
AND total_purchase >= 100000;
在庫管理システム
-- 補充が必要な人気商品を検索
-- (在庫が20個以下で、月間売上が100個以上)
SELECT product_name, stock, monthly_sales
FROM products
WHERE stock <= 20
AND monthly_sales >= 100;
ORの使い方:「または」の条件
ORは「どれかの条件を満たす」ときに使います。
基本的な使い方
-- 東京都または大阪府に住んでいる人
SELECT * FROM customers
WHERE prefecture = '東京都' OR prefecture = '大阪府';
-- ステータスが「完了」または「発送済み」の注文
SELECT * FROM orders
WHERE status = '完了' OR status = '発送済み';
複数の値から選択する
-- カテゴリが「本」「雑誌」「新聞」のいずれかの商品
SELECT * FROM products
WHERE category = '本'
OR category = '雑誌'
OR category = '新聞';
-- 年齢が18歳、20歳、25歳のいずれかの人
SELECT * FROM users
WHERE age = 18 OR age = 20 OR age = 25;
より簡潔な書き方:IN句
ORで同じ列の複数の値を指定する場合、IN句を使うとより簡潔に書けます。
-- ORを使った書き方
SELECT * FROM products
WHERE category = '本' OR category = '雑誌' OR category = '新聞';
-- IN句を使った書き方(同じ意味)
SELECT * FROM products
WHERE category IN ('本', '雑誌', '新聞');
実際の業務での使用例
セール対象商品の検索
-- 割引対象商品を検索
-- (在庫処分商品または季節商品)
SELECT product_name, category, stock
FROM products
WHERE category = '在庫処分'
OR category = '季節限定';
緊急対応が必要なタスク
-- 優先度の高いタスクを検索
-- (優先度が「高」または「緊急」)
SELECT task_name, priority, deadline
FROM tasks
WHERE priority = '高' OR priority = '緊急'
ORDER BY deadline;
NOTの使い方:「ではない」の条件
NOTは条件を否定するときに使います。
基本的な使い方
-- ステータスが「キャンセル」ではない注文
SELECT * FROM orders WHERE NOT status = 'キャンセル';
-- 価格が0円ではない商品
SELECT * FROM products WHERE NOT price = 0;
別の書き方
NOTは他の演算子と組み合わせて、より自然に書くこともできます。
-- NOT = の代わりに <> や != を使う
SELECT * FROM orders WHERE status <> 'キャンセル';
SELECT * FROM orders WHERE status != 'キャンセル';
-- NOT IN を使う
SELECT * FROM products
WHERE category NOT IN ('廃盤', '販売停止');
NULLの扱い
-- メールアドレスが登録されている顧客
SELECT * FROM customers WHERE email IS NOT NULL;
-- 退職していない社員(退職日が未入力)
SELECT * FROM employees WHERE resignation_date IS NULL;
実際の業務での使用例
アクティブユーザーの分析
-- 退会していないユーザーを検索
SELECT user_name, registration_date, last_login
FROM users
WHERE NOT status = '退会済み'
ORDER BY last_login DESC;
正常な商品の在庫確認
-- 問題のない商品を検索
-- (廃盤でも販売停止でもない商品)
SELECT product_name, stock, price
FROM products
WHERE status NOT IN ('廃盤', '販売停止', '在庫切れ');
括弧を使った条件のグループ化
複数の論理演算子を組み合わせるときは、括弧を使って優先順位を明確にしましょう。
なぜ括弧が必要?
SQLでは、ANDがORよりも優先的に処理されます。意図しない結果を避けるために、括弧で条件をグループ化することが重要です。
問題のある例
-- この書き方だと意図しない結果になる可能性がある
SELECT * FROM orders
WHERE status = '完了' OR status = '発送済み' AND date >= '2025-01-01';
上記の条件は、次のように解釈されます:
status = '完了'
(いつでも)- または
status = '発送済み' AND date >= '2025-01-01'
(2025年以降の発送済み)
正しい書き方
-- 括弧を使って意図を明確にする
SELECT * FROM orders
WHERE (status = '完了' OR status = '発送済み') AND date >= '2025-01-01';
この場合は、次のように解釈されます:
status = '完了' OR status = '発送済み'
(完了または発送済み)- かつ
date >= '2025-01-01'
(2025年以降)
実践的な例
優良顧客の検索
-- 購入金額が高いか、購入回数が多い顧客で、かつアクティブな人
SELECT customer_name, total_amount, purchase_count, last_login
FROM customers
WHERE (total_amount >= 100000 OR purchase_count >= 50)
AND last_login >= '2025-05-01';
セール対象商品の検索
-- 在庫が少ないか売れ行きが悪い商品で、かつ廃盤予定でないもの
SELECT product_name, stock, monthly_sales, status
FROM products
WHERE (stock <= 10 OR monthly_sales <= 5)
AND status != '廃盤予定';
緊急対応タスクの検索
-- 締切が近いか優先度が高いタスクで、かつ未完了のもの
SELECT task_name, deadline, priority, status
FROM tasks
WHERE (deadline <= '2025-06-10' OR priority = '緊急')
AND status != '完了';
実際の仕事でよく使う複数条件の例
ECサイトの商品検索
-- セール商品の検索
-- (割引率が20%以上で、在庫があり、評価が3.5以上)
SELECT product_name, price, discount_rate, stock, rating
FROM products
WHERE discount_rate >= 20
AND stock > 0
AND rating >= 3.5
ORDER BY discount_rate DESC;
-- 人気カテゴリの新商品
-- (カテゴリが「家電」「本」「衣類」で、登録から30日以内)
SELECT product_name, category, registration_date
FROM products
WHERE category IN ('家電', '本', '衣類')
AND registration_date >= '2025-05-04' -- 30日前
ORDER BY registration_date DESC;
顧客管理システム
-- 重要顧客の検索
-- (購入金額が50万円以上か購入回数が100回以上で、かつ最近アクティブ)
SELECT customer_name, total_purchase, purchase_count, last_order_date
FROM customers
WHERE (total_purchase >= 500000 OR purchase_count >= 100)
AND last_order_date >= '2025-04-01'
ORDER BY total_purchase DESC;
-- フォローが必要な顧客
-- (最終購入から6ヶ月以上経過しているが、退会はしていない)
SELECT customer_name, last_order_date, status
FROM customers
WHERE last_order_date < '2024-12-03' -- 6ヶ月前
AND status != '退会済み'
ORDER BY last_order_date;
売上分析
-- 好調な売上データ
-- (今年の売上で、10万円以上か前年比150%以上)
SELECT order_date, total_amount, growth_rate
FROM daily_sales
WHERE order_date >= '2025-01-01'
AND (total_amount >= 100000 OR growth_rate >= 1.5)
ORDER BY order_date DESC;
人事管理システム
-- 昇進候補者の検索
-- (勤続年数が3年以上で、評価がAまたはB+で、現在在籍中)
SELECT employee_name, years_of_service, evaluation, department
FROM employees
WHERE years_of_service >= 3
AND evaluation IN ('A', 'B+')
AND resignation_date IS NULL
ORDER BY years_of_service DESC;
よくある間違いと対策
括弧の省略による意図しない結果
問題のあるSQL
-- 意図:「完了または発送済み」で「2025年以降」の注文
-- 実際:「完了」(いつでも)または「発送済みで2025年以降」
SELECT * FROM orders
WHERE status = '完了' OR status = '発送済み' AND order_date >= '2025-01-01';
正しいSQL
SELECT * FROM orders
WHERE (status = '完了' OR status = '発送済み')
AND order_date >= '2025-01-01';
NULLの扱い間違い
間違った例
-- NULLに対して = や != は正しく動作しない
SELECT * FROM customers WHERE email != NULL; -- 間違い
正しい例
-- IS NOT NULL を使う
SELECT * FROM customers WHERE email IS NOT NULL;
-- NULLも含めた条件
SELECT * FROM customers
WHERE email IS NOT NULL OR phone IS NOT NULL;
データ型の混同
問題のある例
-- 文字列として格納された数値の比較
SELECT * FROM products WHERE price_text > '100'; -- '100' > '2' になる場合がある
正しい例
-- 数値型に変換してから比較
SELECT * FROM products WHERE CAST(price_text AS INTEGER) > 100;
-- または、最初から数値型で保存する
SELECT * FROM products WHERE price > 100;
複雑すぎる条件
読みにくい例
SELECT * FROM orders
WHERE status = 'A' OR status = 'B' AND amount > 1000 OR status = 'C' AND amount > 2000 AND date > '2025-01-01';
読みやすい例
SELECT * FROM orders
WHERE status = 'A'
OR (status = 'B' AND amount > 1000)
OR (status = 'C' AND amount > 2000 AND date > '2025-01-01');
パフォーマンスを考えた複数条件の書き方
インデックスを活用できる順番
-- インデックスがある列を最初に書く
SELECT * FROM orders
WHERE customer_id = 123 -- インデックスあり(高速)
AND order_date >= '2025-01-01' -- インデックスあり(高速)
AND total_amount > 10000; -- インデックスなし(低速)
OR条件でのパフォーマンス
-- ORが多い場合は、UNIONを検討する場合もある
-- OR を使った書き方
SELECT * FROM products
WHERE category = 'A' OR category = 'B' OR category = 'C';
-- UNION を使った書き方(場合によっては高速)
SELECT * FROM products WHERE category = 'A'
UNION
SELECT * FROM products WHERE category = 'B'
UNION
SELECT * FROM products WHERE category = 'C';
-- ただし、通常はINの方が簡潔で十分
SELECT * FROM products WHERE category IN ('A', 'B', 'C');
効率的な条件の組み合わせ
-- 悪い例:全件検索してから絞り込み
SELECT * FROM large_table
WHERE expensive_function(column1) = 'value'
AND simple_column = 'simple_value';
-- 良い例:簡単な条件で先に絞り込み
SELECT * FROM large_table
WHERE simple_column = 'simple_value' -- 先に絞り込み
AND expensive_function(column1) = 'value';
応用テクニック
範囲検索との組み合わせ
-- 年齢層別の顧客分析
SELECT customer_name, age, total_purchase
FROM customers
WHERE (age BETWEEN 20 AND 29 OR age BETWEEN 50 AND 59)
AND total_purchase > 50000;
-- 期間限定キャンペーンの対象商品
SELECT product_name, price, campaign_start, campaign_end
FROM products
WHERE campaign_start <= '2025-06-03'
AND campaign_end >= '2025-06-03'
AND (price BETWEEN 1000 AND 5000 OR discount_rate >= 30);
サブクエリとの組み合わせ
-- 平均以上の売上で、かつ特定カテゴリの商品
SELECT product_name, sales_amount, category
FROM products
WHERE sales_amount > (SELECT AVG(sales_amount) FROM products)
AND category IN ('家電', '家具')
AND stock > 0;
CASE文との組み合わせ
-- 条件に応じた分類
SELECT
customer_name,
total_purchase,
CASE
WHEN total_purchase >= 100000 AND purchase_count >= 50 THEN 'VIP'
WHEN total_purchase >= 50000 OR purchase_count >= 20 THEN 'ゴールド'
ELSE 'レギュラー'
END as customer_rank
FROM customers
WHERE status = 'アクティブ';
まとめ
複数条件を使えば、SQLの表現力は格段に広がります。
AND・OR・NOTを使い分けて、現実の要件を正確に反映したデータ抽出が可能になります。
重要なポイント
- AND:すべての条件を満たす(「かつ」)
- OR:どれかの条件を満たす(「または」)
- NOT:条件を否定する(「ではない」)
- 括弧:複雑な条件では必ず使って優先順位を明確にする
- NULL:
IS NULL
とIS NOT NULL
を正しく使う
書き方のコツ
- 複雑な条件は括弧でグループ化する
- 読みやすいように改行とインデントを使う
- インデックスがある列を優先的に条件に含める
- 同じ列の複数値チェックにはINを使う
コメント