SQL 基礎 — RDBMS・SELECT・WHERE・GROUP BY・JOIN
SQL 基礎 — RDBMS・SELECT・WHERE・GROUP BY・JOIN
🎯 このレッスンを読み終えたら
このレッスンをすべて読み終えると、以下の3つを自信を持って実行できるようになります。
- ▸✅ SELECT・WHERE・GROUP BY・HAVING・ORDER BY 句の正確な順序
- ▸✅ INNER JOIN と LEFT JOIN の違い+ケース別の選び方
- ▸✅ EXPLAIN で実行計画を読む方法(
typeとrows列)
学習目標をチェックリストとして意識し、すべてに答えられるようになったらレッスンを閉じてください。
RDBMSのコア概念6つ
一言で: リレーショナルDB = テーブル + PK/FK + 正規化 + ACID + インデックス + SQL。50年の標準。
6つのコア概念
正規化ステップのクイック解説
> 💡 実務では: 通常は3NFまで。パフォーマンスのために意図的な非正規化を行う場合もあります(参照頻度の高い箇所)。
SQL 4分類
SELECT 7句の実行順序
記述順序 vs 実行順序
各句 — 役割とよくある落とし穴
暗記のコツ
- ▸FWG・HSO・L — From-Where-Group / Having-Select-Order / Limit
- ▸データを早めに絞る — WHERE が早いほど後の処理が軽くなる
- ▸インデックスが使われない5つのパターン: 関数・LIKE の左側 %・型変換・NOT・OR
JOIN + GROUP BY パターン
JOIN 5種類の比較
JOIN アンチパターン
アンチジョイン(片側にのみ存在する行):
自己結合(自己参照):
GROUP BY 6パターン
WHERE vs HAVING
💾 実践1 — ユーザー別注文統計(LEFT JOIN + GROUP BY)
-- 入力: users テーブル + orders テーブル
-- 処理: LEFT JOIN で注文なしのユーザーも含める + GROUP BY でユーザーごとに集計
-- 出力: ユーザーごとの注文数と合計支払額(注文0件は0表示)
SELECT
u.id,
u.name,
COUNT(o.id) AS order_count, -- 注文件数
COALESCE(SUM(o.amount), 0) AS total -- 合計支払額(NULL → 0)
FROM users u
LEFT JOIN orders o
ON o.user_id = u.id
AND o.status = 'PAID' -- 決済完了のみ
GROUP BY u.id, u.name
ORDER BY total DESC
LIMIT 5;
💾 実践2 — 月別売上(DATE_TRUNC + HAVING)
-- 入力: orders(created_at、total、status)
-- 処理: 月単位でグループ化 + 決済完了フィルター + 100万以上のみ
-- 出力: 月別注文数と売上
SELECT
DATE_TRUNC('month', created_at)::DATE AS month,
COUNT(*) AS orders,
SUM(total) AS revenue,
ROUND(AVG(total)) AS avg_order
FROM orders
WHERE status = 'PAID'
GROUP BY month
HAVING SUM(total) > 1000000
ORDER BY month;
💾 実践3 — ウィンドウ関数(ユーザー別直近注文 Top 3)
-- 入力: orders
-- 処理: PARTITION BY user_id でユーザーごとにソート → 上位3件
-- 出力: 各ユーザーの最新注文3件
WITH ranked AS (
SELECT
o.*,
ROW_NUMBER() OVER (
PARTITION BY user_id
ORDER BY created_at DESC
) AS rn
FROM orders o
)
SELECT user_id, id AS order_id, total, created_at
FROM ranked
WHERE rn <= 3
ORDER BY user_id, rn;
EXPLAIN — クエリ実行計画の確認
EXPLAIN が必要な理由
同じ結果を返すクエリでも、DBが内部的にどう実行するかによって速度が数十〜数百倍変わることがあります。EXPLAIN は MySQL オプティマイザーの判断を確認するためのツールです。
使い方
結果:
最も重要な列 — type と rows
type のランク — 良い順
1. const / system — 1件確定(PKで検索)。最良。
2. eq_ref — JOINでPK・UNIQUEを使用。非常に良い。
3. ref — インデックス使用。良い。
4. range — 範囲インデックス(WHERE age > 20)。許容範囲。
5. index — インデックス全体スキャン。悪い。
6. ALL — フルテーブルスキャン。最悪 — インデックスなしの状態。
type 列に ALL が表示されたら、インデックスを作成するかクエリを修正してください。
rows — 検査する行数の見積もり
100万行のテーブルで rows: 1000000 → フルスキャン。rows: 5 → インデックスヒット。rows が小さいほど高速。
EXPLAIN ANALYZE — 実際の実行時間まで確認(MySQL 8+)
実際にクエリを実行しながら、各ステップの所要時間を出力します。遅いクエリのデバッグに欠かせないツールです。
実務ワークフロー
1. スロークエリログ(slow_query_log)から1秒以上かかるクエリを収集
2. 各クエリに EXPLAIN を実行
3. type=ALL または rows が大きいクエリ → インデックス追加を検討
4. EXPLAIN ANALYZE で改善前後を比較
🤖 AIへのリクエスト例
このレッスンの概念を知っていれば、AIに具体的な指示を出せます。漠然とした「直して」ではなく、語彙を持ったリクエスト — それがトークン節約の出発点です。
- ▸「users・orders・products の3テーブル設計をFK・INDEXまで含めて作って」
- ▸「直近7日間に登録したユーザー数を日別に集計するクエリを書いて」
- ▸「このクエリにEXPLAINを付けて実行計画を解釈して」
なぜトークンが減るのか
概念を知らないと、AIの回答を受け取っても「それって何ですか?」と再度質問が必要になります。その「再質問」がトークンを消費します。概念を一度身につければ、会話が一度で完結します。