コース一覧
SQL実践:JOIN・サブクエリ・データ更新
INNER JOINの基本

SQL実践:JOIN・サブクエリ・データ更新

JOIN、集合演算、サブクエリ、CTE、DDL・DMLを学び、複数テーブルを組み合わせてデータベースを作成・更新する無料コースです。

1
テーブル結合
01. なぜ結合が必要か5分
02. INNER JOINの基本5分
03. LEFT/RIGHT OUTER JOIN5分
04. 複数テーブルの結合5分
05. 自己結合5分
06. 集合演算 UNION/INTERSECT/EXCEPT5分
07. 結合の実践演習5分
08. テーブル結合クイズ5分
2
サブクエリ活用
01. サブクエリとは5分
02. WHERE句のサブクエリ5分
03. FROM句のサブクエリ5分
04. SELECT句のサブクエリ5分
05. WITH句(CTE)の活用5分
06. サブクエリ実践クイズ5分
3
テーブル作成とデータ操作
01. CREATE DATABASE と CREATE TABLE5分
02. データ型の選び方5分
03. INSERT 文でデータを追加する5分
04. UPDATE 文でデータを更新する5分
05. DELETE 文でデータを削除する5分
06. 物理削除と論理削除5分
07. ALTER TABLE で構造を変更する5分
08. 制約 (NOT NULL / UNIQUE / DEFAULT)5分
09. TRUNCATE と DROP5分
10. DDL / DML 実践クイズ5分

INNER JOINの基本

JOIN で表をつなぐ

JOIN を書いて実行したら、元のテーブルより行数が減っていた。結合を覚えたばかりの頃によくある戸惑いです。減るのは仕様で、しかもその減り方こそが INNER JOIN の正体です。

相手が見つからなかった行は、黙って消える

SQL クエリ

-- 在庫レコードがある商品だけが並ぶ
SELECT p.name, s.quantity
FROM products p
INNER JOIN stocks s
  ON p.id = s.product_id;

在庫テーブルに行が無い商品、たとえば登録したての新商品や廃番品は、この結果には出てきません。INNER JOIN が返すのは「両方のテーブルに相手が見つかった行だけ」だからです。エラーも警告も出ないので、件数を数えて初めて気づきます。

なお INNER は省略できて、JOIN とだけ書いても内部結合になります。

逆に、行が増えることもあります。1 つの商品に在庫レコードが倉庫ごとに 2 行あれば、その商品は結果に 2 行並びます。ON で結ぶ相手が 1 行とは限らない、という当たり前のことが、結合した瞬間に見えにくくなります。

employees · 5 1 / 2 / 2 / 3 / NULL departments · 4 1 / 2 / 3 / 4 一致キー 3 種 1 → 田中 2 → 鈴木 / 佐藤 3 → 高橋 山田 department_id NULL 4 · 総務 社員 0 ON e.department_id = d.id INNER JOIN · 4 行 ORDER BY e.id employee department salary 101 田中 営業 350000 102 鈴木 開発 420000 103 佐藤 開発 380000 104 高橋 人事 320000 山田 / 総務は結果に出ない 重なり 3 キー → 社員 4 行 · 開発 id 2 に 2 人 WHERE はなし · ON の一致だけを残す 山田は NULL で不一致 · 総務 id 4 は社員なし 101 → 104 は JOIN ではなく ORDER BY e.id の順

NULL は誰とも一致しない

結合に使う列が NULL の行も、同じように消えます。NULL は「値が無い」という印なので、NULL = NULL は真になりません。担当者が未設定の商品や、部署が決まっていない社員は、内部結合ではまとめて落ちます。

落としたくない場合は、片側を全部残す結合に切り替えます。逆に「実績のあるものだけを並べたい」売上ランキングのような用途では、相手のいない行が自動的に消えてくれるこの性質がそのまま役に立ちます。

ON は結合の条件、WHERE は結合後の絞り込み

SQL クエリ

SELECT p.name, s.quantity
FROM products p
JOIN stocks s ON p.id = s.product_id
WHERE s.quantity > 0;

ON に書くのは「どの行とどの行を合わせるか」、WHERE に書くのは「合わせた結果から何を残すか」です。内部結合ではどちらに書いても結果が同じになることが多いのですが、片側を全部残す結合では結果が変わります。役割で分けて書く習慣を先に付けておくと、あとで混乱しません。

SQL クエリ

-- 結合の前後で件数を比べる
SELECT COUNT(*) FROM products;
SELECT COUNT(*) FROM products p JOIN stocks s ON p.id = s.product_id;
解説

結合したら必ず件数を確かめてください。増えていれば ON に書いた列が一対多になっていて、減っていれば相手が見つからない行か NULL が混じっています。

テーブル構造

CREATE TABLE departments (
  id INT PRIMARY KEY,
  name VARCHAR(30)
);

CREATE TABLE employees (
  id INT PRIMARY KEY,
  name VARCHAR(30),
  department_id INT,
  salary INT
);

INSERT INTO departments VALUES
  (1, '営業'),
  (2, '開発'),
  (3, '人事'),
  (4, '総務');

INSERT INTO employees VALUES
  (101, '田中', 1, 350000),
  (102, '鈴木', 2, 420000),
  (103, '佐藤', 2, 380000),
  (104, '高橋', 3, 320000),
  (105, '山田', NULL, 300000);

期待される出力

employee_idemployee_namedepartment_namesalary
101田中営業350000
102鈴木開発420000
103佐藤開発380000
104高橋人事320000

ヒント

INNER JOIN departments d ON e.department_id = d.id の形

department_id が NULL の山田は結果から消える点に注目

AS で列名をきれいに整える

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • テーブルDB の表 (Excel のシートみたいなもの)
  • レコードテーブル内の1件分のデータ(行)
  • HTTPWeb の通信プロトコル、HTTPS は TLS で暗号化したもの
  • JOIN複数テーブルをくっつけて 1 つの結果に並べる SQL
query.sql
学習モード
エディタを読み込んでいます
コードの実行結果
データベースを初期化中...