🇯🇵 日本語 | 🇺🇸 English | 🇪🇸 Español | 🇵🇹 Português | 🇹🇭 ไทย | 🇨🇳 中文

【SQL入門】複数条件の達人になろう!AND, OR, NOTを完全マスター

「データベースから特定のデータを取り出したいけど、条件が一つじゃ足りない…」
Webクリエイターとしてステップアップする中で、こんな壁にぶつかったことはありませんか?

データベースを操作する言語、SQL。その中でもデータを抽出するSELECT文は基本中の基本です。しかし、本当に欲しい情報をピンポイントで手に入れるには、複数の条件を組み合わせてデータを絞り込むテクニックが欠かせません。

この記事では、複数条件を指定するための3つの論理演算子、AND, OR, NOTの使い方を、初心者の方でもコピペで動かせるサンプルコード付きで徹底的に解説します!「動いた!」という体験を通して、SQLの面白さと便利さを実感してください。


準備:練習用のテーブルを用意しよう

まずは、この記事で使う練習用のテーブルを作成しましょう。架空の社員情報を格納するemployeesテーブルです。以下のSQL文をコピーして、ご自身のデータベース環境で実行してみてください。

もし、すぐに試せる環境がない場合でも大丈夫!記事の後半で、ブラウザだけでSQLを試せる「SQL実行環境」を用意していますので、まずは読み進めてみてくださいね。


-- テーブルが存在すれば削除
DROP TABLE IF EXISTS employees;

-- 社員テーブルの作成
CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    department VARCHAR(50),
    position VARCHAR(50),
    salary INT,
    hire_date DATE
);

-- データの挿入
INSERT INTO employees (id, name, department, position, salary, hire_date) VALUES
(1, '山田 太郎', '営業部', 'マネージャー', 600000, '2018-04-01'),
(2, '鈴木 花子', '開発部', 'エンジニア', 550000, '2020-10-01'),
(3, '佐藤 次郎', '営業部', 'スタッフ', 400000, '2022-04-01'),
(4, '高橋 三郎', '人事部', 'マネージャー', 650000, '2017-07-01'),
(5, '田中 恵子', '開発部', 'デザイナー', 500000, '2021-08-15'),
(6, '伊藤 四郎', '営業部', 'マネージャー', 700000, '2015-02-01'),
(7, '渡辺 久美', '開発部', 'エンジニア', 750000, '2019-06-01'),
(8, '山本 五郎', '人事部', 'スタッフ', 380000, '2023-04-01'),
(9, '中村 さくら', '開発部', 'マネージャー', 800000, '2016-09-01'),
(10, '小林 健太', '営業部', 'スタッフ', 420000, '2023-10-01');
    

準備はできましたか?このテーブルを使って、条件指定の世界に飛び込んでいきましょう!


1. AND:すべての条件を満たすデータを狙い撃ち!

ANDは、日本語で言うと「~かつ~」という意味です。指定した条件をすべて満たすデータだけを抽出したいときに使います。

例えば、「営業部に所属している」かつ「役職がマネージャー」の社員情報が欲しい、といったケースです。

基本的な使い方

WHERE句の中に、ANDで条件を繋げて記述します。


SELECT *
FROM employees
WHERE department = '営業部' AND position = 'マネージャー';
    

このSQLを実行すると、departmentが'営業部'であり、かつpositionが'マネージャー'である社員のデータがすべて取得できます。山田さんと伊藤さんが該当しますね。


ANDを複数繋げる

ANDはいくつでも繋げることができます。条件を増やせば増やすほど、データはより厳密に絞り込まれます。

例として、「営業部に所属」かつ「役職がマネージャー」かつ「給料が650000円以上」の社員を探してみましょう。


SELECT *
FROM employees
WHERE
    department = '営業部'
    AND position = 'マネージャー'
    AND salary >= 650000;
    

今度は伊藤さんだけがヒットしました。条件が増えたことで、山田さんが除外されたわけです。このようにANDは、条件を重ねてピンポイントでデータを特定したい場合に非常に強力です。


2. OR:いずれかの条件を満たすデータを幅広く取得!

ORは、「~または~」という意味です。指定した条件のいずれか一つでも満たすデータを抽出したいときに使います。

例えば、「営業部に所属している」または「開発部に所属している」社員の一覧が欲しい、といったケースで活躍します。

基本的な使い方

使い方はANDと同じく、WHERE句の中で条件をORで繋ぎます。


SELECT *
FROM employees
WHERE department = '営業部' OR department = '開発部';
    

これを実行すると、所属部署が'営業部'の社員と、'開発部'の社員がすべて表示されます。ANDが条件を重ねて絞り込むのに対し、ORは条件に合うものをどんどん追加していくイメージですね。


ORを複数繋げる

もちろんORも複数繋げられます。「役職がマネージャー」または「給料が700000円以上」の社員を探してみましょう。


SELECT *
FROM employees
WHERE position = 'マネージャー' OR salary >= 700000;
    

この結果には、

が含まれます。伊藤さんと中村さんは両方の条件を満たしていますが、もちろん結果に含まれます。ORは「少なくとも片方を満たしていればOK」という緩やかな条件指定です。


3. NOT:条件に当てはまらないデータを抽出!

NOTは、その名の通り「~ではない」という否定の条件を指定します。ある特定の条件を持つデータを除外したい場合に便利です。

基本的な使い方

WHERE句の、否定したい条件の直前にNOTを置きます。

例として、「開発部ではない」社員をすべて取得してみましょう。


SELECT *
FROM employees
WHERE NOT department = '開発部';
    

これを実行すると、'開発部'に所属する社員以外の、つまり'営業部'と'人事部'の社員が表示されます。
ちなみに、WHERE department != '開発部'WHERE department <> '開発部' と書いても同じ結果が得られます。どちらを使うかは好みやチームの規約によりますが、NOTINEXISTSなど他の演算子と組み合わせることもでき、表現の幅が広いのが特徴です。


【応用編】ANDとORの組み合わせと「括弧」の重要性

さあ、ここからが本番です!ANDORを組み合わせることで、より複雑な条件を指定できるようになります。しかし、ここには初心者がハマりがちな大きな落とし穴があります。それが演算子の優先順位です。

SQLでは、なにも指定しないとANDORよりも先に評価されます。これは、数学の計算で掛け算(×)が足し算(+)より先に行われるのと似ています。

意図した通りのデータを取得するために、数学と同じく()(括弧)を使って、優先順位を明確に指定することが非常に重要になります。

悪い例:「営業部」または「開発部」で、かつ「マネージャー」の社員は?

この条件を何も考えずにSQLにすると、こうなってしまうかもしれません。


-- 意図しない結果になるSQL
SELECT *
FROM employees
WHERE
    department = '営業部'
    OR department = '開発部' AND position = 'マネージャー';
    

このSQL、実行するとどうなるでしょうか?
ANDが優先されるため、SQLはまずdepartment = '開発部' AND position = 'マネージャー'(開発部のマネージャー)を評価します。その結果とdepartment = '営業部'(営業部の全社員)をORで繋ぎます。

つまり、このクエリが探しているのは、

どちらか、ということになってしまいます。これでは「営業部または開発部のマネージャー」という本来の意図とは違いますよね。


良い例:括弧を使って正しくグループ化する

意図した通りに「(営業部 または 開発部)の所属で、かつ役職がマネージャー」という条件にするには、ORで繋いだ部分を()で囲ってあげます。


-- 括弧を使って意図通りに!
SELECT *
FROM employees
WHERE
    (department = '営業部' OR department = '開発部')
    AND position = 'マネージャー';
    

こうすることで、先に(department = '営業部' OR department = '開発部')が評価され、「営業部または開発部に所属する」という一つの条件の塊になります。その結果に対してAND position = 'マネージャー'が評価されるため、正しく「営業部または開発部に所属するマネージャー」を抽出できます。

ANDとORを混ぜて使うときは、必ず括弧()で優先順位を明示する! これを鉄則として覚えておきましょう!


実践!ブラウザでSQLを実行してみよう

お待たせしました!ここまで学んだことを、実際に手を動かして試せる環境のプレゼントです。

これは、JavaScriptのライブラリ(AlaSQL.js)を使って、ブラウザ上でSQLを実行できるようにしたものです。下のコードをまるごとコピーして、sql_practice.htmlのようなファイル名で保存し、ブラウザで開いてみてください。

この記事で紹介した色々なSQLをテキストエリアに貼り付けて、「実行」ボタンを押すと、その場で結果が表示されます。色々試して、データの変化を体感してみてください!


<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>SQL練習場</title>
    <script src="https://cdn.jsdelivr.net/npm/alasql@4"></script>
    <style>
        body { font-family: sans-serif; padding: 2rem; background-color: #f9f9f9; }
        .container { max-width: 800px; margin: auto; background: white; padding: 2rem; border-radius: 8px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); }
        h1 { color: #333; }
        textarea { width: 100%; height: 150px; font-family: monospace; font-size: 16px; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; margin-bottom: 1rem; }
        button { background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; }
        button:hover { background-color: #0056b3; }
        #result-area { margin-top: 2rem; }
        table { width: 100%; border-collapse: collapse; margin-top: 1rem; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        .error { color: red; font-weight: bold; }
    </style>
</head>
<body>
    <div class="container">
        <h1>SQLを試してみよう!</h1>
        <p>下のテキストエリアにSQL文を入力して「実行」ボタンを押してください。記事で紹介した色々なSQLを試してみましょう!</p>
        <textarea id="sql-input">-- この中にSQLを書いてください
SELECT * FROM employees WHERE (department = '営業部' OR department = '開発部') AND position = 'マネージャー';</textarea>
        <button onclick="executeSQL()">SQLを実行</button>
        <div id="result-area"></div>
    </div>

    <script>
        // データの準備
        const createTableSQL = `
            CREATE TABLE employees (
                id INT, name STRING, department STRING, position STRING, salary INT, hire_date DATE
            );
        `;
        const insertDataSQL = `
            INSERT INTO employees VALUES
            (1, '山田 太郎', '営業部', 'マネージャー', 600000, '2018-04-01'),
            (2, '鈴木 花子', '開発部', 'エンジニア', 550000, '2020-10-01'),
            (3, '佐藤 次郎', '営業部', 'スタッフ', 400000, '2022-04-01'),
            (4, '高橋 三郎', '人事部', 'マネージャー', 650000, '2017-07-01'),
            (5, '田中 恵子', '開発部', 'デザイナー', 500000, '2021-08-15'),
            (6, '伊藤 四郎', '営業部', 'マネージャー', 700000, '2015-02-01'),
            (7, '渡辺 久美', '開発部', 'エンジニア', 750000, '2019-06-01'),
            (8, '山本 五郎', '人事部', 'スタッフ', 380000, '2023-04-01'),
            (9, '中村 さくら', '開発部', 'マネージャー', 800000, '2016-09-01'),
            (10, '小林 健太', '営業部', 'スタッフ', 420000, '2023-10-01');
        `;

        // AlaSQLのデータベースを初期化
        const db = new alasql.Database();
        db.exec(createTableSQL);
        db.exec(insertDataSQL);

        function executeSQL() {
            const sql = document.getElementById('sql-input').value;
            const resultArea = document.getElementById('result-area');
            resultArea.innerHTML = ''; // 前回の結果をクリア

            try {
                const result = db.exec(sql);
                if (result.length > 0) {
                    resultArea.appendChild(createTable(result));
                } else {
                    resultArea.innerHTML = '<p>結果は0件でした。</p>';
                }
            } catch (e) {
                resultArea.innerHTML = `<p class="error">エラー: ${e.message}</p>`;
            }
        }

        function createTable(data) {
            const table = document.createElement('table');
            const thead = table.createTHead();
            const tbody = table.createTBody();
            const headerRow = thead.insertRow();

            // ヘッダー作成
            for (const key in data[0]) {
                const th = document.createElement('th');
                th.textContent = key;
                headerRow.appendChild(th);
            }

            // データ行作成
            data.forEach(rowData => {
                const row = tbody.insertRow();
                for (const key in rowData) {
                    const cell = row.insertCell();
                    cell.textContent = rowData[key];
                }
            });
            return table;
        }

        // 初期表示
        executeSQL();
    </script>
</body>
</html>
    

気をつけるべき点と関連テクニック

最後に、複数条件を扱う上での注意点と、関連する便利な演算子をいくつか紹介します。

NULLの扱い

データベースにはNULLという特殊な値が存在します。これは「データが存在しない」ことを示す空っぽの状態です。
注意すべきは、NULL=!= で比較できない点です。NULLかどうかを判定するには、専用の IS NULL または IS NOT NULL を使います。


-- salaryが設定されていない(NULL)社員を探す
SELECT * FROM employees WHERE salary IS NULL;

-- salaryが設定されている(NULLではない)社員を探す
SELECT * FROM employees WHERE salary IS NOT NULL;
    

今回のサンプルデータにはNULLはありませんが、実際の開発では頻繁に登場します。WHERE salary = NULL と書いてもエラーにはなりませんが、意図した結果は得られないので注意しましょう。


より便利な条件指定:IN と BETWEEN

ORANDをたくさん書くのを、もっとシンプルにできる場合があります。

IN: ORの代わりに

「営業部、人事部、経理部のいずれか」のように、同じカラムに対して複数の値をORで繋ぐ場合、INを使うとスッキリ書けます。


-- ORをたくさん書く場合
SELECT * FROM employees
WHERE department = '営業部' OR department = '人事部';

-- INでスッキリ書く場合
SELECT * FROM employees
WHERE department IN ('営業部', '人事部');
    

BETWEEN: ANDの代わりに

「給料が400000円以上、かつ600000円以下」のように、数値や日付の範囲を指定する場合はBETWEENが便利です。


-- ANDで範囲を指定する場合
SELECT * FROM employees
WHERE salary >= 400000 AND salary <= 600000;

-- BETWEENでスッキリ書く場合
SELECT * FROM employees
WHERE salary BETWEEN 400000 AND 600000;
    

これらの演算子も、もちろんANDORNOTと組み合わせて使えます。表現の引き出しとして持っておくと、よりスマートなSQLが書けるようになりますよ。


まとめ

お疲れ様でした!今回は、SQLで複数の条件を指定するための基本となるAND, OR, NOTについて、具体的な例を交えながら学びました。

これらの論理演算子をマスターすれば、複雑な条件でも思いのままにデータを抽出できるようになり、あなたのデータ操作スキルは格段に向上します。

今回紹介したSQL実行環境などを活用して、ぜひ色々な条件を試してみてください。SQLは、書けば書くほど、試せば試すほど上達します。この記事が、あなたのSQLマスターへの道のりの一助となれば幸いです!