データモデリングとは
いきなり CREATE TABLE を書くと、3 か月後に作り直しになる
会議室の予約システムを作ることになりました。仕様書を読んで、その場で CREATE TABLE を書き始めます。会議室の名前、予約者、開始時刻、終了時刻。列は思いついた順に並んでいきます。
3 か月後、「1 件の予約に複数人を登録したい」という要件が来ます。予約者の列は 1 本しかありません。participant2 を足すか、1 つのセルにカンマ区切りで詰め込むか。どちらを選んでも、その次の要件でまた詰まります。
コードなら書き直せます。しかし本番データが入ったテーブルは、列の意味を変えた瞬間に全機能が止まります。先に決めておくべきだったのは列ではなく、登場人物と、その間に引く線でした。
登場人物を洗い出してから、列に落とす
データモデリングとは、業務を「テーブルと関連」に翻訳する作業です。翻訳は 3 段階に分けて進めます。
最初の段階は、業務担当の説明をそのまま書き取り、出てきた名詞に丸を付けるところから始まります。「会議室を、社員が、日時を指定して予約する」なら、丸が付くのは会議室、社員、予約の 3 つです。ここでは列を 1 つも決めません。丸が付いた名詞のうち、どれを表にするかだけを決めます。
| 段階 | ここで決めること | 出てくるもの |
|---|---|---|
| 概念モデル | 業務に出てくる登場人物 | 会議室、予約、参加者 |
| 論理モデル | 各登場人物が持つ列と、関連の向き | 属性を書き込んだ図 |
| 物理モデル | 型、制約、インデックス | CREATE TABLE 文 |
段階を分ける理由は、混ぜると議論が止まるからです。「参加者は予約とは別に持つべきか」という業務の話と、「主キーは INT か文字列か」という実装の話を同時に進めると、業務担当も開発者も自分の話ができなくなります。概念モデルは業務担当と一緒に描き、物理モデルは開発側だけで決められます。
線は、多側の 1 本の列になる
「1 つの会議室に、予約が何件も入る」と決めたとします。この線は、物理モデルでは多側 (予約) に列を 1 本置く形で現れます。
SQL クエリ
CREATE TABLE rooms (
id INT PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE reservations (
id INT PRIMARY KEY,
room_id INT NOT NULL,
started_at TIMESTAMP NOT NULL
);reservations.room_id が、図で引いた線そのものです。線を先に引いておけば、列の置き場所で迷いません。逆に列から書き始めると、線を引き忘れたことに気づくのは、アプリ側で「会議室ごとに予約を数えるループ」を書き始めたときになります。
表を増やすことを怖がらないでください。登場人物ごとに分けておけば、後は JOIN するだけで元の形に戻せます。1 枚に詰め込むと、使わない列が NULL で埋まり、読むたびに「この行ではこの列は何を意味するのか」を考えることになります。
テーブル構造
CREATE TABLE users (
id INT PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE tasks (
id INT PRIMARY KEY,
title TEXT NOT NULL,
assignee_id INT
);
INSERT INTO users (id, name) VALUES
(1, '田中'),
(2, '鈴木'),
(3, '佐藤');
INSERT INTO tasks (id, title, assignee_id) VALUES
(1, '要件定義', 1),
(2, '画面設計', 1),
(3, 'DB設計', 2),
(4, 'コーディング', 2),
(5, 'テスト', 2);期待される出力
| assignee | task_count |
|---|---|
| 田中 | 2 |
| 鈴木 | 3 |
| 佐藤 | 0 |