データベース設計 / 約20分
JOINとLEFT JOIN: テーブルをまたいで集計する
なぜこれを学ぶか
実務のデータは複数テーブルに分かれています。「ユーザー名つきの売上一覧」のように、テーブルを「繋ぐ」JOIN は、SQLの実用度を一気に引き上げる最重要トピックです。
JOIN(内部結合) は、両方のテーブルに対応する行がある組み合わせだけを取り出します: FROM users u JOIN orders o ON o.user_id = u.id。ON に書くのが「結合条件」です。
LEFT JOIN(左外部結合) は、左側のテーブルの行を「すべて」残します。右側に対応行がなければ NULL になります。「注文が0件のユーザーも一覧に出したい」ときに必須です。
テーブルには 別名(エイリアス) を付けるのが実務標準です: users u のように短くすると、u.name o.amount と書けてクエリが読みやすくなります。
JOIN と GROUP BY の組み合わせが定番です: 「ユーザーごとの注文数」= users と orders を結合 → ユーザーでグループ化 → COUNT。第1章の演習もこの形でした。
LEFT JOIN で「件数」を数えるときは COUNT(*) ではなく COUNT(o.id) を使います。COUNT(*) は行そのものを数えるため注文0件でも1と数えてしまい、COUNT(列) は NULL を数えないため正しく0になります。
重要ポイント
- JOIN = 両方にある行だけ、LEFT JOIN = 左の全行を保持
- テーブル別名(users u)でクエリを短く読みやすく
- LEFT JOIN の件数は COUNT(o.id)(COUNT(*) だと0件が1になる)
理解度チェック
選ぶと即座に解説が表示されます。
「注文が0件のユーザーも含めて、全ユーザーの注文数」を出したい。適切な結合は?
ヒントを見る
「0件の人も残す」= 片方のテーブルに対応行がなくても行を消さない結合方式が必要です。
SQL演習ブラウザ内SQLite
最終演習です。users テーブルと orders テーブルを LEFT JOIN して、「全ユーザーの注文数」を取得してください。要件: ①注文が0件のユーザーも結果に含める ②列はユーザー名(name)と注文数(order_count) ③注文数の多い順、同数ならユーザーIDの昇順。
テーブル定義と初期データを見る
CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);
CREATE TABLE orders (id INTEGER PRIMARY KEY, user_id INTEGER, amount INTEGER);INSERT INTO users VALUES (1, '田中'), (2, '佐藤'), (3, '鈴木'), (4, '高橋');
INSERT INTO orders VALUES
(1, 1, 3000), (2, 2, 1500), (3, 1, 2000),
(4, 2, 4500), (5, 1, 800), (6, 3, 1200);スキルセルフチェック
このレッスンの内容をどの程度理解できましたか?