今回やること
この記事では、users と orders の2つのテーブルを作り、INNER JOIN と LEFT JOIN を練習します。
JOINは、別々のテーブルに保存したデータを、必要なときに関係づけて読むために使います。
前提条件
- SQLの
SELECTとWHEREを読める - 学習用データベースで試す
- JOINの細かい最適化ではなく、結果の違いを理解する
Step 1: テーブルを作る
ユーザーと注文を別テーブルに分けます。
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL,
total INTEGER NOT NULL
);
学習用なので外部キー制約は省略しています。実務では orders.user_id に外部キーを設定することが多いです。
Step 2: データを入れる
INSERT INTO users (id, name) VALUES
(1, 'Sato'),
(2, 'Suzuki'),
(3, 'Tanaka');
INSERT INTO orders (id, user_id, total) VALUES
(101, 1, 3000),
(102, 1, 1500),
(103, 2, 5000);
Tanaka には注文がありません。この状態を使ってJOINの違いを確認します。
Step 3: INNER JOINを試す
SELECT
users.id,
users.name,
orders.id AS order_id,
orders.total
FROM users
INNER JOIN orders ON users.id = orders.user_id;
INNER JOIN では、注文があるユーザーだけが結果に残ります。
確認するポイントは、Sato が2行出ることです。これは Sato に注文が2件あるためです。
Step 4: LEFT JOINを試す
SELECT
users.id,
users.name,
orders.id AS order_id,
orders.total
FROM users
LEFT JOIN orders ON users.id = orders.user_id;
LEFT JOIN では、左側の users が全員残ります。注文がない Tanaka は、注文側の列が NULL になります。
一覧画面で「注文がないユーザーも表示したい」ならLEFT JOINを使います。
Step 5: 注文があるユーザーだけにする
注文があるユーザーだけなら INNER JOIN が自然です。
SELECT DISTINCT users.id, users.name
FROM users
INNER JOIN orders ON users.id = orders.user_id;
Sato は注文が2件あるため、DISTINCT を付けないと2行出ます。
Step 6: 注文がないユーザーを探す
LEFT JOIN と IS NULL を組み合わせます。
SELECT users.id, users.name
FROM users
LEFT JOIN orders ON users.id = orders.user_id
WHERE orders.id IS NULL;
これは「ユーザー一覧を残したうえで、対応する注文がない行だけを取る」SQLです。
Step 7: JOIN後にWHEREで絞る
3000円以上の注文を持つユーザーを見ます。
SELECT users.name, orders.total
FROM users
INNER JOIN orders ON users.id = orders.user_id
WHERE orders.total >= 3000;
ここでは、ON はテーブルのつなぎ方、WHERE は結果の絞り込みです。
よくあるエラー
| エラー | よくある原因 | 確認すること |
|---|---|---|
| 行数が多すぎる | ON 条件が間違っている | users.id = orders.user_id になっているか |
| 注文なしユーザーが出ない | INNER JOIN を使っている | LEFT JOIN を使う |
id が曖昧と言われる | 両テーブルに id がある | users.id のようにテーブル名を付ける |
| LEFT JOINなのに件数が減る | 右側条件をWHEREに書いている | 条件の位置を確認する |
まとめ
INNER JOIN は対応する行があるデータだけを返し、LEFT JOIN は左側の行を残します。注文がないユーザーを探すには、LEFT JOIN してから右側のキーが NULL の行を探します。