コース一覧
SQL入門:データベース操作のきほん
第2正規形 (2NF)

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分

第2正規形 (2NF)

商品名を直したいだけなのに、明細 800 行を書き換える

注文明細を 1 枚の表にまとめました。主キーは「どの注文の、どの商品か」の 2 列の組です。

SQL クエリ

CREATE TABLE order_items_bad ( order_id INT, product_id INT, product_name VARCHAR(100), unit_price INT, quantity INT, PRIMARY KEY (order_id, product_id) );

商品名を「ノート」から「A4 ノート」に変えることになりました。この商品は 800 件の注文に登場しています。書き換える行は 800 行です。

1 行でも漏れると、商品別の集計に「ノート」と「A4 ノート」が別の商品として 2 行並びます。価格改定でも同じことが起きて、古い単価の行と新しい単価の行が混ざり、売上の合計が誰にも説明できない数字になります。

主キーの一部だけで決まる列を探す

なぜ 800 行に散らばったのかを、主キーとの関係から見ます。この表の主キーは (order_id, product_id) の 2 列です。列を 1 本ずつ点検します。

  • quantity — どの注文の、どの商品かが両方分かって初めて決まる
  • product_name — product_id だけで決まる。order_id は関係ない
  • unit_price — 同じく product_id だけで決まる

product_id が決まれば product_name も決まる、という関係を product_id → product_name と書き、関数従属と呼びます。そのうち、主キーの一部だけで決まっているものが部分関数従属です。product_id は主キー 2 列のうちの 1 列なので、product_name と unit_price がこれに当たります。

主キー全体が要る列と、一部で足りる列を同じ表に同居させると、一部で足りる列は組み合わせの数だけ複製されます。800 行の重複は、これが原因です。

決まる側の表へ引っ越させる

product_id だけで決まる列は、product_id が主キーになっている表へ移します。

SQL クエリ

CREATE TABLE products ( id INT PRIMARY KEY, name VARCHAR(100), unit_price INT ); CREATE TABLE order_items ( order_id INT, product_id INT, quantity INT, PRIMARY KEY (order_id, product_id) );

商品名の変更も価格改定も、products の 1 行を書き換えるだけになります。明細側に残るのは、その注文でだけ決まる quantity です。読むときに商品名や単価が要れば、product_id を手がかりに商品の表から取ってきます。

第 2 正規形とは、主キーの一部だけで決まる列が残っていない状態のことです。この問題は複合主キーの表でしか起きません。主キーが id 1 列の表には「一部」というものが存在しないので、点検の対象になるのは主キーが 2 列以上ある表だけです。

テーブル構造

CREATE TABLE products ( id INT PRIMARY KEY, name VARCHAR(100), unit_price INT ); CREATE TABLE order_items ( order_id INT, product_id INT, quantity INT, PRIMARY KEY (order_id, product_id) ); INSERT INTO products VALUES (10, 'ノート', 300), (11, 'ペン', 150), (12, '消しゴム', 100); INSERT INTO order_items VALUES (1001, 10, 2), (1001, 11, 4), (1002, 10, 1), (1003, 12, 3), (1004, 11, 5), (1005, 10, 6);

期待される出力

nametotal_amount
ノート2700
ペン1350
消しゴム300

ヒント

products と order_items を product_id で JOIN

金額 = unit_price * quantity を SUM する

GROUP BY p.id, p.name で商品単位に集計

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

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

  • 外部キーテーブル同士を結びつける鍵
  • 主キーレコードを一意に特定する列
  • 関数処理に名前を付けて再利用できる単位
  • 関数従属ある列が決まれば別の列も決まる関係
query.sql
学習モード
エディタを読み込んでいます
コードの実行結果
データベースを初期化中...