コース一覧
SQL実践: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分

自己結合

売上表を出したら「前日と比べてどうだった?」と聞かれた。今日の行も昨日の行も同じテーブルの中に両方あるのに、1 行に並べて比べる書き方が思いつかない。自己結合はここで効きます。

同じテーブルに 2 つの名前を付けると、別のテーブルになる

SQL クエリ

-- 今日と前日の売上を 1 行に並べる
SELECT a.day, a.sales AS today, b.sales AS prev_day
FROM daily_sales a
LEFT JOIN daily_sales b
  ON b.day = a.day - INTERVAL '1 day'
ORDER BY a.day;

FROM daily_sales a と JOIN daily_sales b は同じテーブルですが、a と b という別名を付けた瞬間、SQL からは 2 つの別々のテーブルに見えます。あとは普通の結合と同じで、ON に「a の何と b の何が同じなら横に並べるか」を書くだけです。

別名は省略できません。FROM daily_sales JOIN daily_sales ON ... と書くと、どちらのテーブルの列を指しているのか決められずエラーになります。

一番端の行が消えたら、内部結合を疑う

SQL クエリ

-- 前日のデータが無い初日が消える
SELECT a.day, a.sales AS today, b.sales AS prev_day
FROM daily_sales a
JOIN daily_sales b ON b.day = a.day - INTERVAL '1 day';

内部結合では、相手が見つからない行が落ちます。前日が存在しない初日は、この書き方だと結果に出てきません。

同じことは上下関係をたどるときにも起きます。親を持たない一番上の行、組織図なら社長、カテゴリ表なら最上位カテゴリは、内部結合では必ず消えます。トップが出てこないレポートはほぼバグなので、階層をたどる自己結合では LEFT JOIN を選び、相手側の列が NULL のままでも行が残るようにします。

自分自身とペアを組ませない

SQL クエリ

-- 同じカテゴリに属する商品の組み合わせを作る
SELECT a.name AS product, b.name AS related
FROM products a
JOIN products b
  ON a.category = b.category
 AND a.id <> b.id
ORDER BY a.id, b.id;

条件が a.category = b.category だけだと、商品は自分自身とも一致してしまい「A と A」という無意味な行が混ざります。a.id <> b.id を足して自分を除きます。

たどれるのは 1 段だけ、という点も押さえておいてください。社員から課長、その上の部長、さらに役員と何段も一気に展開したいときは、自己結合を重ねるのではなく再帰的な WITH RECURSIVE を使うのが正攻法です。

解説

書く前に、同じテーブルのコピーを 2 枚並べたところを頭に浮かべてください。どちらを「自分」、どちらを「相手」とするかが決まれば、あとは普通の結合と変わりません。

テーブル構造

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

INSERT INTO employees VALUES
  (1, '社長',  NULL),
  (2, '部長A', 1),
  (3, '部長B', 1),
  (4, '課長X', 2),
  (5, '課長Y', 2),
  (6, '一般a', 4),
  (7, '一般b', 5);

期待される出力

employee_idemployee_namemanager_name
1社長NULL
2部長A社長
3部長B社長
4課長X部長A
5課長Y部長A
6一般a課長X
7一般b課長Y

ヒント

FROM employees e LEFT JOIN employees m ON e.manager_id = m.id

別名を 2 つ用意することで同じテーブルを 2 つの視点で扱える

社長は manager_id が NULL なので LEFT JOIN を使うと NULL のまま残る

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

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

  • テーブルDB の表 (Excel のシートみたいなもの)
  • SQLデータベースを操作するための共通言語
  • 階層ネットワークを役割ごとに積み重ねた構造
  • 再帰関数が自分自身を呼び出す処理パターン
query.sql
学習モード
エディタを読み込んでいます
コードの実行結果
データベースを初期化中...