コース一覧
SQL入門:データベース操作のきほん
自己結合

SQL入門:データベース操作のきほん

SELECT、INSERT、UPDATE、DELETE に加え、WHERE、JOIN、GROUP BY、サブクエリなど SQL の基礎構文を、ブラウザ上のサンプル DB を操作しながら学べる無料コースです。データ分析やアプリ開発で SQL を初めて学ぶ社会人や学生を対象としています。約 18 時間 (1 日 30 分 × 36 日) で 71 レッスンを修了でき、修了後は業務データの抽出、集計、簡単なレポート作成を SQL で行えるようになります。

1
SQLとデータベースの基礎
01. データベースとは何か5分
02. リレーショナルDBの仕組み5分
03. テーブル・行・列の基本5分
04. 主キーとNULL制約5分
05. 基礎確認クイズ5分
2
データの取得 - SELECT文マスター
01. SELECT文の基本構文5分
02. WHERE句で条件絞り込み5分
03. 比較演算子とLIKEパターン5分
04. AND/OR/NOTで複合条件5分
05. ORDER BYでソート5分
06. LIMITで件数制限5分
07. 日付関数の活用5分
08. データ取得チャレンジ5分
3
データ集計と分析
01. 集計関数 COUNT/SUM/AVG/MAX/MIN5分
02. NULLの扱い方5分
03. 算術演算とエイリアス5分
04. CASE式で条件分岐5分
05. DISTINCTで重複排除5分
06. 文字列関数5分
07. GROUP BYでグループ化5分
08. HAVINGでグループ条件5分
09. SELECT文の実行順序5分
10. 集計分析チャレンジ5分
4
テーブル結合
01. なぜ結合が必要か5分
02. INNER JOINの基本5分
03. LEFT/RIGHT OUTER JOIN5分
04. 複数テーブルの結合5分
05. 自己結合5分
06. 集合演算 UNION/INTERSECT/EXCEPT5分
07. 結合の実践演習5分
08. テーブル結合クイズ5分
5
サブクエリ活用
01. サブクエリとは5分
02. WHERE句のサブクエリ5分
03. FROM句のサブクエリ5分
04. SELECT句のサブクエリ5分
05. WITH句(CTE)の活用5分
06. サブクエリ実践クイズ5分
6
テーブル作成とデータ操作
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分
7
外部キーと参照整合性
01. 外部キーの役割5分
02. FOREIGN KEY制約の設定5分
03. ON DELETE/UPDATE ポリシー5分
04. CASCADE vs RESTRICT vs SET NULL5分
05. 物理FK vs 論理FK5分
06. 外部キークイズ5分
8
データモデリング入門
01. データモデリングとは5分
02. ER図の読み方・書き方5分
03. エンティティと属性5分
04. リレーションシップとカーディナリティ5分
05. 1対1/1対多/多対多の設計5分
06. モデリング基礎クイズ5分
9
正規化
01. なぜ正規化が必要か5分
02. 第1正規形 (1NF)5分
03. 第2正規形 (2NF)5分
04. 第3正規形 (3NF)5分
05. 非正規化の判断5分
06. 正規化クイズ5分
10
物理設計とインデックス
01. 物理設計の考え方5分
02. 命名規則のベストプラクティス5分
03. インデックスの仕組み5分
04. CREATE INDEXの使い方5分
05. インデックス設計の注意点5分
06. 物理設計クイズ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
学習モード
エディタを読み込んでいます
コードの実行結果
データベースを初期化中...