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

【SQL入門】WHERE句を徹底解説!コピペで学ぶデータ抽出の真髄

Webサイトやアプリケーションを制作するWebクリエーターの皆さん、「データベース」や「SQL」と聞くと、少し専門的で自分には関係ないと感じていませんか?しかし、現代のWeb制作において、SQLの知識はあなたのクリエイティビティを次のレベルへと引き上げる強力な武器になります。

例えば、WordPressのようなCMSの裏側では、投稿データやユーザー情報がデータベースに保存されています。SQLを知っていれば、特定の条件に合う記事だけを抜き出して表示する、といった高度なカスタマイズが可能になります。また、ユーザーの行動履歴から人気コンテンツを分析し、データに基づいたWebサイト改善を行う際にもSQLは必須です。つまり、SQLはもはやバックエンドエンジニアだけのものではありません。

この記事では、SQLの中でも特に重要な「WHERE句」に焦点を当てます。WHERE句は、膨大なデータの海から、あなたが必要とする情報だけを正確に釣り上げるための「魔法の網」です。初心者の方でも安心して学べるよう、たくさんの「コピペしてすぐ動く」サンプルコードと共に、その使い方を基礎から応用まで徹底的に解説します。実際に手を動かしながら、「データが意のままに動く」面白さをぜひ体験してください!


まずは準備から!物語の舞台となるサンプルテーブル

これから始まるSQLの冒険のために、まずは物語の舞台となるサンプルテーブル `users` を用意しましょう。このテーブルには、架空のWebサービスのユーザー情報が格納されているとイメージしてください。各カラム(列)がどのような情報を持っているのか、しっかり理解しておくと後の学習がスムーズになります。

テーブル定義: `users`

後の「実践コーナー」では、以下のSQLで作成されるテーブルとデータが自動的に読み込まれます。ここではまず、どのようなデータが登録されるのか、じっくり眺めてみてください。

-- テーブルの構造を定義
CREATE TABLE users (
  id INT PRIMARY KEY,
  name VARCHAR(50),
  age INT,
  pref VARCHAR(50),
  points INT
);

-- テーブルにサンプルデータを挿入
INSERT INTO users (id, name, age, pref, points) VALUES
(1, '田中 太郎', 25, '東京都', 120),
(2, '鈴木 一郎', 32, '大阪府', 85),
(3, '佐藤 花子', 28, '東京都', 300),
(4, '高橋 次郎', 45, '福岡県', 50),
(5, '伊藤 さくら', 25, '北海道', NULL),
(6, '渡辺 三郎', 32, '東京都', 150),
(7, '山本 四郎', 51, '大阪府', 210);

WHERE句の基本 - シンプルな条件でデータを絞り込む

WHERE句は `SELECT * FROM users` のような、すべてのデータを取得する文の直後に記述します。基本形は `WHERE カラム名 演算子 値` です。言葉で見るより、実際に動かしてみるのが一番です。早速、基本的な比較演算子を使ってみましょう。

`=` : 完全に一致するデータを探す

最も基本となるのが、等価演算子 `=` です。例えば「25歳のユーザー」だけをピンポイントで探したい場合に使います。値が数値の場合はそのまま、文字列の場合はシングルクォーテーション(`'`)で囲むのがルールです。

SELECT * FROM users WHERE age = 25;

`<>` or `!=` : 条件に一致しないデータを探す

「~ではない」という条件を指定したい場合は `>` と `<` を組み合わせた ` <>` または `!=` を使います。例えば「東京都出身ではないユーザー」を一覧にしたい、といった場合に非常に便利です。

SELECT * FROM users WHERE pref <> '東京都';

`>` と `>=` : より大きい、または以上のデータを探す

数値の大小を比較することも簡単です。「保有ポイントが100より多い(100を含まない)優良顧客」を探してみましょう。`>` を使います。

SELECT * FROM users WHERE points > 100;

もし「32歳以上のユーザー」のように、境界の値を含めたい場合は `=` を付け加えた `>=` を使います。この `=` があるかないかで結果が変わるため、仕様をしっかり確認することが重要です。

SELECT * FROM users WHERE age >= 32;

WHERE句の応用 - 複雑な条件で自在にデータを操る

基本が身につけば、次はいよいよ応用です。複数の条件を組み合わせたり、便利な演算子を使ったりすることで、WHERE句はさらにその真価を発揮します。

`AND` と `OR` : 複数条件の組み合わせ

`AND` は「AかつB」のように、複数の条件をすべて満たすデータを抽出します。「東京都に住んでいて、なおかつ年齢が30歳未満の若手ユーザー」を探してみましょう。

SELECT * FROM users WHERE pref = '東京都' AND age < 30;

一方、`OR` は「AまたはB」のように、いずれかの条件を満たせばデータを抽出します。「大阪府のユーザー、もしくは50歳以上のユーザー」をまとめてリストアップしたい場合に便利です。

SELECT * FROM users WHERE pref = '大阪府' OR age >= 50;

`IN` : 複数の値をまとめて指定

「東京都、大阪府、福岡県のいずれかに住んでいるユーザー」を探したい場合、`pref = '東京都' OR pref = '大阪府' OR pref = '福岡県'` と書くこともできますが、条件が増えると大変です。こんな時は `IN` を使うと、コードが劇的にスッキリします。可読性が上がるだけでなく、データベースによっては処理が高速になるメリットもあります。

SELECT * FROM users WHERE pref IN ('東京都', '大阪府', '福岡県');

`BETWEEN` : 特定の範囲内を指定

「年齢が30歳から50歳までのユーザー」のように、数値の範囲で絞り込みたい場合は `BETWEEN` が便利です。`age >= 30 AND age <= 50` と書くのと同じ意味ですが、より直感的に範囲を指定できます。`BETWEEN` は指定した両端の値を含む(以上、以下)点に注意してください。

SELECT * FROM users WHERE age BETWEEN 30 AND 50;

`LIKE` : あいまい検索の達人

`LIKE` は文字列の部分一致を検索できる強力な演算子です。これには「ワイルドカード」と呼ばれる特殊な記号を使います。

例えば、名前に「郎」が含まれるユーザーを探す(中間一致)には、探したい文字の前後を `%` で挟みます。

SELECT * FROM users WHERE name LIKE '%郎%';

名字が「佐藤」で始まるユーザーを探す(前方一致)場合は、こう書きます。

SELECT * FROM users WHERE name LIKE '佐藤%';

`IS NULL` : 「何もない」を探す

データベースにおける `NULL` とは、「データが存在しない」ことを示す特殊な状態です。「0」や空の文字列(`''`)とは全く異なります。この `NULL` を検索するには `=` ではなく `IS NULL` という特別な構文を使います。「ポイント情報が未登録のユーザー」を探してみましょう。

SELECT * FROM users WHERE points IS NULL;

逆に、`NULL` ではない(何かしらの値が入っている)データを検索する場合は `IS NOT NULL` を使います。

SELECT * FROM users WHERE points IS NOT NULL;

初心者がつまずきやすい3つの注意点

非常に便利なWHERE句ですが、いくつか注意しないと思わぬ落とし穴にはまってしまうことがあります。特に重要な3つのポイントを押さえておきましょう。

  1. `AND`と`OR`の優先順位と括弧 `()`
    SQLでは、`AND` は `OR` よりも先に処理されるというルールがあります。そのため、複雑な条件を組み合わせる際は意図しない結果になることがあります。例えば「東京都または大阪府在住で、かつ30歳以上のユーザー」を抽出したい場合、`OR`で指定したい条件を `()` で囲み、「ここをひとまとまりとして先に計算してね」とデータベースに教えてあげる必要があります。この括弧の使い方は、複雑な条件指定をマスターする上で非常に重要です。
  2. -- (A OR B) AND C という条件
    SELECT * FROM users WHERE (pref = '東京都' OR pref = '大阪府') AND age >= 30;

  3. データ型を意識する
    条件に指定する値は、カラムのデータ型に合わせるのが基本です。文字列なら `'` で囲み、数値なら囲みません。データベースによっては、例えば数値型のカラムに `'123'` のように文字列で値を指定しても、よしなに解釈して動いてくれる(暗黙の型変換)ことがあります。しかし、これはパフォーマンスの低下を招いたり、意図しない結果を生む原因になったりするため、絶対に頼るべきではありません。常に正しいデータ型を意識する癖をつけましょう。
  4. `NULL` は「無」である
    先述の通り、`NULL` は特殊です。`points = 0` と `points IS NULL` は全く意味が異なります。例えば、`COUNT(points)` のようにポイントを持つユーザーの人数を数えた場合、`points` が `NULL` のユーザーはカウントされません。しかし `COUNT(*)` ですべての行数を数えると、`NULL` のユーザーも含まれます。この違いを理解しておくと、データ集計の際にミスを防げます。

データの抽出だけじゃない!WHERE句の真の力

WHERE句の活躍の場は、データの抽出を行う `SELECT` 文だけではありません。データの更新(`UPDATE`)や削除(`DELETE`)においても、対象を正確に指定するために不可欠な役割を果たします。

もし、`DELETE FROM users` というSQLでWHERE句を付け忘れたら…?想像するだけで恐ろしいですが、テーブル内の全データが跡形もなく消え去ります。これは取り返しのつかない大事故につながります。データを変更・削除する前には、必ず `SELECT` 文で意図したデータだけが抽出されるかを確認する、という手順を踏むのがプロフェッショナルの鉄則です。

-- まずはSELECTで対象を確認!
SELECT * FROM users WHERE id = 3;

-- 対象が正しいことを確認してから、UPDATEを実行する
-- UPDATE users SET points = points + 50 WHERE id = 3;

【実践】ブラウザでSQLを動かしてみよう!

お待たせしました!ここで、この記事で学んだSQLを実際にあなたのブラウザで動かしてみましょう。下のコードをまるごとコピーして、`sql-practice.html` のような名前でファイルに保存し、ブラウザで開いてください。

これは、JavaScriptのライブラリ(`sql.js`)を使って、ブラウザ内に一時的なデータベースを作成する魔法のような仕組みです。左側のテキストエリアに、この記事で紹介したSQL文を色々コピー&ペーストして「SQL実行」ボタンを押してみてください。右側に結果がリアルタイムで表示されるはずです。色々な条件を試して、WHERE句の動きをその目で確かめてください!

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>SQL 実行環境 (WHERE句 実践)</title>
    <style>
        body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; display: flex; flex-direction: column; height: 100vh; margin: 0; background-color: #f9f9f9; }
        .header { padding: 15px 20px; background-color: #fff; border-bottom: 1px solid #ddd; }
        .main-content { display: flex; flex: 1; overflow: hidden; }
        .container { flex: 1; display: flex; flex-direction: column; padding: 20px; overflow-y: auto; }
        .container:first-child { border-right: 1px solid #ddd; }
        h3 { margin-top: 0; color: #333; }
        textarea { height: 200px; border: 1px solid #ccc; border-radius: 4px; padding: 10px; font-family: "SF Mono", "Fira Code", "Source Code Pro", monospace; font-size: 14px; margin-top: 10px; resize: vertical; }
        button { background-color: #007bff; color: white; border: none; padding: 12px 18px; border-radius: 4px; cursor: pointer; margin-top: 10px; font-size: 16px; transition: background-color 0.2s; }
        button:hover { background-color: #0056b3; }
        table { border-collapse: collapse; width: 100%; margin-top: 10px; background-color: #fff; }
        th, td { border: 1px solid #ddd; padding: 10px; text-align: left; }
        th { background-color: #f2f2f2; font-weight: 600; }
        #error { color: #d9534f; font-weight: bold; margin-top: 10px; white-space: pre-wrap; }
    </style>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/sql-wasm.js"></script>
</head>
<body>
    <div class="header">
      <h2 style="margin: 0;">SQL WHERE句 実践コーナー</h2>
    </div>
    <div class="main-content">
      <div class="container">
          <h3>SQL入力</h3>
          <textarea id="sql-input">-- このSQLを書き換えて試してみよう!
SELECT * FROM users WHERE pref = '東京都';</textarea>
          <button onclick="executeSql()">SQL実行</button>
          <div id="error"></div>
      </div>
      <div class="container">
          <h3>実行結果</h3>
          <div id="result-table"></div>
      </div>
    </div>
    <script>
        let db;
        async function initDb() {
            try {
                const config = { locateFile: filename => `https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/${filename}` };
                const SQL = await initSqlJs(config);
                db = new SQL.Database();
                const initialSql = `
                  CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(50), age INT, pref VARCHAR(50), points INT);
                  INSERT INTO users (id, name, age, pref, points) VALUES
                  (1, '田中 太郎', 25, '東京都', 120),
                  (2, '鈴木 一郎', 32, '大阪府', 85),
                  (3, '佐藤 花子', 28, '東京都', 300),
                  (4, '高橋 次郎', 45, '福岡県', 50),
                  (5, '伊藤 さくら', 25, '北海道', null),
                  (6, '渡辺 三郎', 32, '東京都', 150),
                  (7, '山本 四郎', 51, '大阪府', 210);
                `;
                db.run(initialSql);
                executeSql(); // 初期表示
            } catch (e) {
                document.getElementById('error').textContent = "データベースの初期化に失敗しました: " + e.message;
            }
        }

        function executeSql() {
            const sqlInput = document.getElementById('sql-input').value;
            const errorEl = document.getElementById('error');
            const resultEl = document.getElementById('result-table');
            errorEl.textContent = '';
            resultEl.innerHTML = '';

            try {
                const results = db.exec(sqlInput);
                if (results.length > 0) {
                    resultEl.appendChild(createTable(results[0]));
                } else {
                    resultEl.innerHTML = '<p>クエリは成功しましたが、結果はありませんでした。(例: UPDATE文など)</p>';
                }
            } catch (e) {
                errorEl.textContent = "SQLエラー: " + e.message;
            }
        }

        function createTable(result) {
            const table = document.createElement('table');
            const thead = document.createElement('thead');
            const tbody = document.createElement('tbody');
            
            const headerRow = document.createElement('tr');
            result.columns.forEach(col => {
                const th = document.createElement('th');
                th.textContent = col;
                headerRow.appendChild(th);
            });
            thead.appendChild(headerRow);

            result.values.forEach(row => {
                const tr = document.createElement('tr');
                row.forEach(cell => {
                    const td = document.createElement('td');
                    td.textContent = cell === null ? 'NULL' : cell; // NULLを文字列として表示
                    tr.appendChild(td);
                });
                tbody.appendChild(tr);
            });

            table.appendChild(thead);
            table.appendChild(tbody);
            return table;
        }

        initDb();
    </script>
</body>
</html>

まとめと次のステップ

今回は、SQLのWHERE句について、その基本から応用、そして実践までを駆け足で見てきました。WHERE句が、いかに柔軟でパワフルなデータ抽出ツールであるかを感じていただけたのではないでしょうか。

WHERE句をマスターすることは、ゴールではなく、広大なSQLの世界への入り口です。もしあなたがさらに深く学びたいと思ったら、次のステップとして以下のテーマに挑戦してみることをお勧めします。

これらの知識を身につければ、あなたのデータ操作能力は飛躍的に向上し、Webクリエーターとしての活躍の場がさらに広がることでしょう。この記事が、その素晴らしい冒険の第一歩となることを心から願っています。