0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【SQL初心者向け】JOINをサンプルデータで理解する|INNER・LEFT・RIGHT・FULLの違い

0
Posted at

はじめに

SQLの JOIN は、複数のテーブルを関連付けてデータを取得する機能です。図だけで暗記するより、結合条件と結果の行を実際に確認する方が理解しやすくなります。この記事はPostgreSQLの構文を基準に説明します。

練習用テーブルを作る

CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name VARCHAR(30) NOT NULL
);

CREATE TABLE orders (
    id INTEGER PRIMARY KEY,
    user_id INTEGER,
    amount INTEGER NOT NULL
);

INSERT INTO users (id, name) VALUES
(1, '田中'), (2, '佐藤'), (3, '鈴木');

INSERT INTO orders (id, user_id, amount) VALUES
(101, 1, 3000), (102, 1, 1500), (103, 2, 2000), (104, 99, 500);

ここではJOINの違いを見せるため、orders.user_id=99 のような対応するユーザーがいないデータを意図的に含めています。本番システムなら外部キー制約などで整合性を確保するのが一般的です。

users

id name
1 田中
2 佐藤
3 鈴木

orders

id user_id amount
101 1 3000
102 1 1500
103 2 2000
104 99 500

1. INNER JOIN:一致した行だけ

SELECT u.name, o.id AS order_id, o.amount
FROM users AS u
INNER JOIN orders AS o ON u.id = o.user_id
ORDER BY o.id;
name order_id amount
田中 101 3000
田中 102 1500
佐藤 103 2000

鈴木には注文がなく、注文104には対応するユーザーがないため結果に出ません。

2. LEFT JOIN:左側をすべて残す

SELECT u.name, o.id AS order_id, o.amount
FROM users AS u
LEFT JOIN orders AS o ON u.id = o.user_id
ORDER BY u.id, o.id;
name order_id amount
田中 101 3000
田中 102 1500
佐藤 103 2000
鈴木 NULL NULL

LEFT JOIN では左側の users を残します。右側に該当行がなければ、その列が NULL になります。

3. RIGHT JOIN:右側をすべて残す

SELECT u.name, o.id AS order_id, o.amount
FROM users AS u
RIGHT JOIN orders AS o ON u.id = o.user_id
ORDER BY o.id;
name order_id amount
田中 101 3000
田中 102 1500
佐藤 103 2000
NULL 104 500

RIGHT JOIN はテーブルの左右を入れ替えた LEFT JOIN で表現できることも多いです。

4. FULL OUTER JOIN:両方の行を残す

SELECT u.name, o.id AS order_id, o.amount
FROM users AS u
FULL OUTER JOIN orders AS o ON u.id = o.user_id
ORDER BY o.id NULLS LAST, u.id;
name order_id amount
田中 101 3000
田中 102 1500
佐藤 103 2000
NULL 104 500
鈴木 NULL NULL

FULL OUTER JOIN はPostgreSQLでは利用できますが、DB製品によっては直接サポートされません。

5. 1対多では行が増える

田中は注文を2つ持つので、JOIN結果でも2行になります。JOINした結果が増えたからといって、必ずしも重複データやSQLのバグとは限りません。

6. よくある落とし穴:WHERE句でLEFT JOINが絞り込まれる

-- 注文のない鈴木は結果から除外される
SELECT u.name, o.amount
FROM users AS u
LEFT JOIN orders AS o ON u.id = o.user_id
WHERE o.amount >= 2000;

右表の NULL 行は o.amount >= 2000 を満たさないため、残りません。

-- 左表を全件残し、条件を満たす注文だけ結合する
SELECT u.name, o.amount
FROM users AS u
LEFT JOIN orders AS o
  ON u.id = o.user_id AND o.amount >= 2000;

こちらは鈴木の行も残ります。また、条件に合う注文のないユーザーもNULL行として残ります。

7. JOINで特に気をつけたいこと

  • ON に結合キーを書き忘れると意図しない組み合わせが大量に増える場合があります。
  • SELECT * では同名列が並び、結果の意味が分かりにくくなります。必要な列を指定しましょう。
  • 結果の並びは ORDER BY を明記しなければ保証されません。
  • テーブル名には別名(u、o)を付けると読みやすくなります。

まとめ

INNER JOIN は一致行のみ、LEFT JOIN は左表を残す、RIGHT JOIN は右表を残す、FULL OUTER JOIN は両方を残す。実務では結果が何行になるかを考えて使うのがおすすめです。

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?