SQLとは何か?

SQL(Structured Query Language、構造化問い合わせ言語)は、リレーショナルデータベースを操作するための標準言語です。1970年代にIBMで開発されて以来、半世紀近く現役で使われ続けている、Webアプリケーションのバックエンドでは欠かせない技術です。

MySQL、PostgreSQL、SQLite、Oracle、SQL Serverなど、多くのRDBMS(リレーショナルデータベース管理システム)が共通の文法でSQLを使えるため、一度覚えれば長く役立ちます。

💡 SQLは「宣言的」な言語です。つまり「何が欲しいか」を書くだけで、「どうやって取得するか」はDBエンジンが勝手に決めてくれます。

テーブルの基礎

リレーショナルデータベースでは、データはテーブル(表)として管理されます。例えば「ユーザー一覧」のテーブルは以下のようなイメージです:

idnameemailage
1田中太郎[email protected]30
2鈴木花子[email protected]25
3佐藤次郎[email protected]42

列(カラム)には型があり、各行(レコード)がデータの1件分を表します。

テーブルの作成(CREATE TABLE)

CREATE TABLE users (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(100) NOT NULL,
  email VARCHAR(255) UNIQUE NOT NULL,
  age INT,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

この例で押さえておきたいキーワード:

  • PRIMARY KEY:行を一意に識別する主キー
  • AUTO_INCREMENT:自動的に連番が振られる
  • NOT NULL:NULLを許容しない
  • UNIQUE:重複を許容しない
  • DEFAULT:未指定時のデフォルト値

SELECT:データの取得

SQLで最もよく使うのが SELECT 文です。

-- 全件取得(非推奨:本番では避ける)
SELECT * FROM users;

-- 特定の列だけ取得
SELECT name, email FROM users;

-- 条件で絞り込み
SELECT * FROM users WHERE age >= 30;

-- 並べ替え
SELECT * FROM users ORDER BY age DESC;

-- 件数制限
SELECT * FROM users LIMIT 10;

WHERE句で使える演算子

-- 等しい
WHERE age = 30

-- 範囲
WHERE age BETWEEN 20 AND 40

-- リスト
WHERE id IN (1, 3, 5)

-- パターンマッチ(%は任意の文字列、_は1文字)
WHERE name LIKE '田%'      -- 「田」で始まる
WHERE email LIKE '%@gmail.com'

-- NULL判定
WHERE age IS NULL
WHERE age IS NOT NULL

-- 複合条件
WHERE age >= 20 AND name LIKE '田%'
WHERE age < 18 OR age > 65
⚠️ SELECT *は便利ですが、本番のクエリでは必要なカラムだけを明示的に書きましょう。不要なデータ転送を減らせるうえ、テーブル構造の変更にも強くなります。

INSERT・UPDATE・DELETE

INSERT(挿入)

-- 1件挿入
INSERT INTO users (name, email, age)
VALUES ('山田太郎', '[email protected]', 28);

-- 複数件まとめて挿入
INSERT INTO users (name, email, age) VALUES
  ('Aさん', '[email protected]', 22),
  ('Bさん', '[email protected]', 35),
  ('Cさん', '[email protected]', 40);

UPDATE(更新)

-- 特定行の更新(必ずWHEREを書く!)
UPDATE users
SET age = 31, email = '[email protected]'
WHERE id = 1;
⚠️ WHEREを書き忘れると全行が書き換えられます。本番DBで実行する前は必ず確認してください。多くのDBクライアントには「セーフモード」(WHEREなしのUPDATE/DELETEを禁止する設定)があります。

DELETE(削除)

-- 特定行の削除
DELETE FROM users WHERE id = 5;

-- 条件に合うすべての行を削除
DELETE FROM users WHERE age < 18;

JOIN:テーブルの結合

実際のシステムでは、データは複数のテーブルに分かれて格納されています。例えば「ユーザー」と「投稿」を別テーブルにして、関連付けで管理するのが一般的です。

-- usersテーブルとpostsテーブル
-- posts.user_id が users.id を参照する

-- INNER JOIN:両方に存在するデータのみ取得
SELECT users.name, posts.title
FROM users
INNER JOIN posts ON users.id = posts.user_id;

-- LEFT JOIN:左側のテーブルは全件、右側は一致するもの
SELECT users.name, posts.title
FROM users
LEFT JOIN posts ON users.id = posts.user_id;
-- 投稿がないユーザーも結果に含まれる(postsの列はNULL)

JOINの種類まとめ

種類結果
INNER JOIN両方のテーブルに一致するレコードのみ
LEFT JOIN左テーブル全件 + 右テーブルの一致分(無ければNULL)
RIGHT JOIN右テーブル全件 + 左テーブルの一致分
FULL OUTER JOIN両方のテーブル全件(一致しない部分はNULL)

集計:GROUP BY と集計関数

「ユーザーごとの投稿数」「年齢別の平均値」のような集計にはGROUP BYを使います。

-- 主な集計関数
SELECT
  COUNT(*) AS total,           -- 件数
  AVG(age) AS avg_age,         -- 平均
  SUM(age) AS sum_age,         -- 合計
  MAX(age) AS max_age,         -- 最大
  MIN(age) AS min_age          -- 最小
FROM users;

-- グループ化して集計
SELECT user_id, COUNT(*) AS post_count
FROM posts
GROUP BY user_id
ORDER BY post_count DESC;

-- HAVING で集計後の絞り込み
SELECT user_id, COUNT(*) AS post_count
FROM posts
GROUP BY user_id
HAVING COUNT(*) >= 5;
💡 WHEREは集計前の絞り込み、HAVINGは集計後の絞り込みです。混同しがちなのでセットで覚えましょう。

インデックス:高速化の鍵

テーブルに大量データが入ってくると、検索が遅くなります。インデックス(索引)を貼ることで、特定カラムでの検索を劇的に速くできます。

-- インデックス作成
CREATE INDEX idx_users_email ON users(email);

-- 複合インデックス(複数カラム)
CREATE INDEX idx_posts_user_date ON posts(user_id, created_at);

-- インデックス削除
DROP INDEX idx_users_email ON users;

インデックスの注意点

  • 検索は速くなるが、INSERT/UPDATE/DELETEは遅くなる(索引も更新が必要なため)
  • すべての列に貼ればいいわけではない。WHERE/JOIN/ORDER BYで使う列に貼る
  • カーディナリティ(値のばらつき)が高い列ほど効果が大きい(性別など2値しかないものは効果薄)

トランザクション

「複数のSQLをまとめて、すべて成功するか、すべて失敗扱いにするか」を実現するのがトランザクションです。

BEGIN;  -- トランザクション開始

UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;

-- 全部成功なら確定
COMMIT;

-- どこかで失敗したら巻き戻し
-- ROLLBACK;

送金のように「片方だけ成功すると整合性が壊れる」処理では必須です。

SQL学習を効率化する3つのコツ

  1. 手を動かす:SQLite(インストール簡単)やDBeaver(GUIクライアント)で実際に動かす
  2. EXPLAINを読む:クエリの実行計画を確認する習慣をつけると、遅いクエリの原因が見えるようになる
  3. サブクエリよりJOINを優先:可読性とパフォーマンスの両面で有利になることが多い

まとめ

  • SELECT:データ取得の基本。WHERE、ORDER BY、LIMITを組み合わせる
  • INSERT/UPDATE/DELETE:データ操作。WHEREの書き忘れに注意
  • JOIN:複数テーブルを関連付けて取得。INNERとLEFTの違いを理解する
  • GROUP BY:集計の基本。HAVINGで集計後の絞り込み
  • インデックス:検索高速化の要。貼りすぎは逆効果
  • トランザクション:整合性が必要な処理で必須

SQLは奥深い言語ですが、まずは基本のSELECT・JOIN・GROUP BYを使いこなせるようになるだけで実務の8割はカバーできます。次はあなたの好きなRDBMSをインストールして、実際に手を動かしてみましょう!