SQLite | ゼロからはじめるSQL、30日で習得するSQLite:検索力強化 - Day14 結合①

SQL SQLite
スポンサーリンク

Day14 前半

「バラバラのテーブルを“意味のある1枚”にくっつける」のが JOIN

ここまでずっと、1つのテーブルだけを相手にしてきました。
users なら users だけ、orders なら orders だけ、という世界です。

でも、現実のアプリはほぼ必ず「複数テーブル」で成り立っています。

ユーザー情報は users
注文情報は orders
商品情報は products

など、役割ごとにテーブルが分かれているのが普通です。

Day14 のテーマ INNER JOIN は、
この「バラバラのテーブル」を、共通のキーを使って“意味のある1枚”にくっつける技 です。

ここを越えると、SQL が一気に「実務の道具」になります。


まずはテーブルを2枚用意するイメージから

シンプルな例でいきます。
次の2つのテーブルを考えます。

users テーブル:

id | name
---+-----------
 1 | 山田太郎
 2 | 佐藤花子
 3 | 鈴木一郎

orders テーブル:

id | user_id | amount
---+---------+-------
 1 | 1       | 1200
 2 | 1       | 3000
 3 | 2       | 500
 4 | 4       | 8000

ここで重要なのは、

users.idorders.user_id が「対応するキー」になっていることです。
「この注文は、どのユーザーのものか」をつなぐ橋ですね。

ただし、orders には user_id = 4 という行があり、
users には id=4 のユーザーはいません。
(わざと“片方にしかいないデータ”を混ぜています。後で効いてきます。)


やりたいことを日本語で言うとこうなる

この2つのテーブルを見ながら、次の問いを考えます。

「各注文について、“誰がいくら買ったのか”を一覧で見たい」

人間の頭の中では、こうやっています。

orders の1行目:user_id=1 → users の id=1 を探す → 山田太郎 → 「山田太郎が1200円」
orders の2行目:user_id=1 → 山田太郎 → 「山田太郎が3000円」
orders の3行目:user_id=2 → 佐藤花子 → 「佐藤花子が500円」
orders の4行目:user_id=4 → users にいない → どう扱うかは後で考える

この「片方のテーブルのキーを見て、もう片方から対応する行を持ってくる」作業を、
SQL にやらせるのが JOIN です。


INNER JOIN の基本形

「両方に存在する組み合わせだけを残す結合」

INNER JOIN の基本形はこうです。

SELECT 列たち
FROM   左側のテーブル
INNER JOIN 右側のテーブル
  ON 結びつける条件;
SQL

さっきの問いを SQL にすると、こうなります。

SELECT
  users.id,
  users.name,
  orders.amount
FROM users
INNER JOIN orders
  ON users.id = orders.user_id;
SQL

ここで起きていることを、丁寧に言葉にするとこうです。

まず、users と orders の行を、
users.id = orders.user_id が一致する組み合わせだけに絞る。
その組み合わせごとに、SELECT に書いた列を1行として出す。

結果はこうなります。

id | name     | amount
---+----------+-------
1  | 山田太郎 | 1200
1  | 山田太郎 | 3000
2  | 佐藤花子 | 500

ここで重要なのは、

orders.user_id = 4 の行は、users.id = 4 が存在しないので、結果から消えていることです。

これが INNER JOIN の本質 です。

「両方のテーブルに“対応する相手”がいる行の組み合わせだけを残す」
片方にしかいないものは、結果から落ちる。


なぜ INNER JOIN が「最重要」なのか

理由はシンプルで、実務で一番使うからです。

ユーザーと注文を結びつける
注文と商品を結びつける
ユーザーとプロフィールを結びつける

こうした「正しく紐づいているデータだけを扱いたい」場面では、
ほぼすべて INNER JOIN を使います。

逆に、「片方にしかいないデータも含めたい」ような特殊なケースで、
LEFT JOIN / RIGHT JOIN などが出てきますが、
まずは INNER JOIN を“呼吸レベル”にする のが先です。


ON 句が超重要

「どの列とどの列を結びつけるか」を明示する

INNER JOIN で一番大事なのは、ON 句です。

... 
INNER JOIN orders
  ON users.id = orders.user_id;
SQL

この ON users.id = orders.user_id が、
「この2つのテーブルは、この列同士で結びつける」という宣言です。

もしここを間違えると、

全然関係ない列同士で結びつけてしまう
意図しない組み合わせが大量にできる(いわゆる“掛け算状態”)

といった事故が起きます。

テーブル設計の段階で、

users.id はユーザーの主キー
orders.user_id は、そのユーザーを指す外部キー

という関係をちゃんと作っておくのは、
JOIN を安全に書くための前提条件でもあります。


テーブルに別名を付けて読みやすくする

JOIN を書き始めると、
users.idusers.nameorders.amount のように、
テーブル名を何度も書くことになります。

これを読みやすくするために、テーブルに別名(エイリアス)を付けるのが定番です。

SELECT
  u.id,
  u.name,
  o.amount
FROM users AS u
INNER JOIN orders AS o
  ON u.id = o.user_id;
SQL

usersuorderso と短くしているだけです。
結果はさっきと同じ。

実務では、ほぼ必ずこの書き方をします。
特に JOIN が増えてくると、別名なしでは読めたものじゃなくなります。


INNER JOIN とセキュリティの関係

「本当に紐づいているデータだけを見る」という防御

セキュリティの視点から見ると、INNER JOIN の「片方にいないものは落とす」という性質は、かなり重要です。

たとえば、

users に存在しない user_id を持つ orders がある
→ データ不整合、あるいは不正なデータの可能性

INNER JOIN で usersorders を結びつけると、
そうした「怪しい注文」は結果から落ちます。

監査やレポートを作るときに、

「正規のユーザーに紐づいているデータだけを対象にする」

というのは、かなり大事な防御線です。

もちろん、「紐づいていないデータが存在すること自体」を検知するクエリも別途必要ですが、
まずは JOIN するときに“正しい関係だけ”を前提にする という姿勢が重要です。


小さな練習イメージ

頭の中で、次の日本語を SQL にしてみてください。

「全ての注文について、ユーザー名と金額を一覧で見たい」
「user_id と amount だけでなく、ユーザーの id と name も一緒に出したい」

どちらも、

FROM users u
INNER JOIN orders o ON u.id = o.user_id

という骨格に、SELECT で欲しい列を足していく形になります。


Day14 前半のまとめ

INNER JOIN は、「両方のテーブルに対応する相手がいる行の組み合わせだけ」を残す結合。
users.idorders.user_id のような「キー同士」を ON 句で結びつける。
結果の1行は、「users の1行」と「orders の1行」が合体した“論理的な1行”になる。
片方にしか存在しないデータ(不整合・不正の可能性があるもの)は、INNER JOIN の結果からは落ちる。
実務では、まず INNER JOIN を“反射で書ける”レベルにするのが最重要。

後半では、
INNER JOIN と WHERE / ORDER BY の組み合わせ、
複数テーブルを連鎖的に JOIN する例(users × orders × products)、
JOIN を使った集計(ユーザー名付きで合計購入金額を出す)
まで踏み込んで、「JOIN した結果をどう活かすか」を一緒に固めていきます。

タイトルとURLをコピーしました