なぜRDB設計者に「1つの階層表」が重要なのか ― Structured Tidy Data(構造化Tidyデータ)

Views: 0

リレーショナル・データベースは、業務システムのリアルタイム処理に非常に適しています。
現在のデータを更新し、正規化された複数の表をJOINし、整合性を保ちながらトランザクションを処理することは、RDBが最も得意とする領域です。

しかし、長期保存は別の問題です。

過去の取引を何年も後に再利用するためには、取引行だけを保存しておけばよいとは限りません。
その取引を正しく理解するには、当時のマスターデータ、スキーマ、コード表、JOIN条件、さらにアプリケーション固有のルールまで必要になることがあります。

Structured Tidy Data(構造化Tidyデータ)は、この異なる要求に対応するための表現です。

1. セマンティックなオブジェクトモデルから始める

ここでは、次の4つのクラスを例にします。

  • JournalEntry

  • JournalLine

  • TaxDetail

  • Account

JournalEntry は1件以上の JournalLine を持ちます。
JournalLine は繰り返し可能な TaxDetail を持つことができ、1つの Account を参照します。
各クラスには、それぞれ entry_idline_idtax_idaccount_id というunique identifierがあります。

UMLセマンティック・オブジェクトモデル
Figure 1. UMLセマンティック・オブジェクトモデル

意味の正本はこのセマンティックモデルです。
クラス、属性、カーディナリティ、関連をここで定義します。
問題は、このモデルから得られるデータを、どのように保存・交換するかです。

2. RDB設計者なら通常どうするか

通常のRDBでは、このモデルを複数のリレーションに分解します。

通常のE-R表現
Figure 2. 通常のE-R表現

これは業務システムのデータベースとして自然な設計です。

2.1. JournalEntry

entry_id entry_date journal_code description

H001

2026-09-01

SALES

Sale of Product X

H002

2026-09-02

PURCHASE

Purchase of Material A

2.2. JournalLine

entry_id line_id debit_credit_code account_id amount

H001

D001

debit

1100

100.00

H001

D002

credit

4000

100.00

H002

D003

debit

5000

80.00

H002

D004

credit

2100

80.00

2.3. TaxDetail

entry_id line_id tax_id tax_category tax_rate tax_amount

H002

D003

T001

Standard

10

8.00

2.4. Account

account_id account_name account_type

1100

Cash

Asset

4000

Sales

Revenue

5000

Purchases

Expense

2100

Accounts Payable

Liability

アプリケーションの永続化には、この分解が最適である場合が多いでしょう。
各クラスを別の表に置き、外部キーで関係を再構成できます。

しかし、交換や長期保存を考えると、別の問題が生じます。

一つの業務記録の意味が、複数の表やファイルに分散するからです。

3. 歴史データの長期保存は別の問題

過去の JournalLine に、次の情報しか保存されていないとします。

account_id = 1100
amount     = 100.00

何年か後にこのデータを正しく解釈するには、1100 がその当時何を意味していたかを示す Account マスターも必要です。

同じ問題は次のようなデータにもあります。

  • 税コード

  • 取引先

  • 通貨

  • 商品

  • 組織

  • その他の参照マスター

Header と Line も、整合した一式として保存されていなければなりません。
片方だけ復元しても、参照切れや不完全な取引記録になる可能性があります。

データベースのバックアップを保存すれば、その状態自体を残すことはできます。
しかし将来再利用するためには、正しい

  • データベース・バージョン

  • スキーマ

  • マスターデータ

  • コード表

  • アプリケーション・ロジック

  • JOINルール

まで復元しなければならないことがあります。

これは障害復旧には適しています。
しかし、持ち運び可能な長期保存形式として常に最適とは限りません。

Important

正規化は業務処理には非常に有効です。しかし、正規化されたデータベースが、そのまま自己完結した歴史記録になるとは限りません。

長期保存では、取引を理解するために必要な情報を、業務システム内では複数表に分かれていても、一緒に保存できることが重要です。

4. では、全部をフラットにすればよいのか

別の方法として、JournalEntry の属性をすべて JournalLine の各行にコピーしたCSVを作ることができます。

しかし、今度は別の問題が生じます。

entry_id entry_date description line_id account_id amount

H001

2026-09-01

Sale of Product X

D001

1100

100.00

H001

2026-09-01

Sale of Product X

D002

4000

100.00

entry_datedescription が明細行ごとに繰り返されます。
TaxDetail が複数あれば、重複はさらに増えます。

矩形の表としては読みやすくなりますが、どの属性がどのクラスに属するのかが曖昧になります。
本来 JournalEntry に属する値が、物理的には JournalLine の各行にコピーされてしまいます。

構造化Tidyデータは、この二つの極端な方法を避けます。

  • セマンティッククラスごとに必ず別の物理表を要求しない

  • 親クラスの属性を子クラスの行に繰り返さない

5. 構造化Tidyデータ とは何か

構造化Tidyデータ は、複数のセマンティッククラスのoccurrenceを、1つの疎な表に格納する、モデル管理された表形式です。

基本原則は単純です。

  1. 1行は1つのclass occurrenceを表す。

  2. 属性値は、その属性を所有するクラスの行にだけ記録する。

  3. 繰り返しクラスは、Tax1Tax2Tax3 のような番号付き列ではなく、追加の行として表す。

  4. 階層occurrence列で親子関係を保持する。

  5. 参照関係は明示的に保持する。

  6. 空欄は構造的な意味を持つ。通常は「値が不明」ではなく、「この列は別のクラスに属する」ことを示す。

簡略化した例を示します。

class dEntry dLine dAccount dTax entry_id entry_date line_id debit_credit amount tax_id tax_rate tax_amount account_id account_name

JournalEntry

1

H001

2026-09-01

JournalLine

1

1

D001

debit

100.00

Account

1

1

1

1100

Cash

JournalLine

1

2

D002

credit

100.00

Account

1

2

1

4000

Sales

JournalEntry

2

H002

2026-09-02

JournalLine

2

1

D003

debit

80.00

TaxDetail

2

1

1

T001

10

8.00

Account

2

1

1

5000

Purchases

JournalLine

2

2

D004

credit

80.00

Account

2

2

1

2100

Accounts Payable

Note
class 列は、説明のために、各行がどの Class に属するかを示したものです。実データに存在する列ではありません。

RDB設計者には、この表は見慣れない形に見えます。
複数のセマンティッククラスが1つの物理表の中に共存しているからです。

しかし、これは意図した設計です。

この表は業務DBを置き換えるためのものではありません。
セマンティックなデータセットを持ち運ぶための表現です。

Note
次の例では、TaxDetail および Account Class は繰り返しがないため、上位の JournalEntry と同じ行に記録しています。Class の階層は維持されますが、繰り返しのない Class のために別の物理行を設ける必要はありません。
class dEntry dLine entry_id entry_date line_id debit_credit amount tax_id tax_rate tax_amount account_id account_name

JournalEntry

1

H001

2026-09-01

JournalLine
(Account)

1

1

D001

debit

100.00

1100

Cash

JournalLine
(Account)

1

2

D002

credit

100.00

4000

Sales

JournalEntry

2

H002

2026-09-02

JournalLine
(TaxDetail)
(Account)

2

1

D003

debit

80.00

T001

10

8.00

5000

Purchases

JournalLine
(Account)

2

2

D004

credit

80.00

2100

Accounts Payable

6. なぜこの形式が重要なのか

この見慣れない形によって、次の3つを同時に実現できます。

  1. 1つの持ち運び可能なデータセット
    完全な業務記録を、アプリケーション固有の複数リレーションではなく、1つの管理された表として受け渡せます。

  2. 親属性を重複させない
    JournalEntry の属性は JournalEntry 行にだけ存在し、各 JournalLine にコピーしません。

  3. 階層と参照関係を明示的に保持する
    JournalEntryJournalLineTaxDetailAccount の関係を、表形式のまま機械的に追跡できます。

RDB設計者にとって重要なのは、目的が違うという点です。

業務用RDB 構造化Tidyデータ

現在のトランザクション処理に最適化

交換、確認、長期保存、分析に最適化

複数の正規化された物理表

複数のセマンティッククラスを1つの疎な表に収容可能

JOINによって関係を再構成

occurrence contextと明示的参照で階層を保持

マスターデータは別の場所に存在することがある

解釈に必要な参照情報を同じデータセットに含められる

運用DBのスキーマやアプリケーション規約に依存

共有セマンティックモデルによって管理

7. AIにとってもなぜ有用なのか

構造化Tidyデータは、取引を理解するために必要な情報を、1つのモデル管理されたデータセットとして保存できるため、AIによる分析にも適しています。

通常の正規化RDBでは、AIが過去の取引を正しく理解するために、取引行だけでなく、

  • データベーススキーマ

  • 主キー・外部キー関係

  • 当時のマスターデータ

  • コード表

  • JOINルール

  • アプリケーション固有の知識

まで必要になることがあります。

account_id = 1100 という値だけでは意味は十分ではありません。
その歴史時点で 1100Cash を意味し、Asset に分類されていたことも分からなければなりません。

構造化Tidyデータでは、JournalEntryJournalLineTaxDetailAccount などの関連クラスを同じデータセットに含めることができます。
各値は、その値を所有するクラスの行にだけ記録され、階層occurrence情報によって行同士の関係を保持します。

したがって AI にとっての利点は、単に「表の方がデータベースより読みやすい」ということではありません。

Important

より重要なのは、データを解釈するために必要なセマンティック・コンテキストを、保存データと一緒に持ち運べることです。

AIは、元の業務データベースとそのJOINを完全に再構築しなくても、過去の取引を調べることができます。

8. まとめ

構造化Tidyデータは、RDBを否定する考え方ではありません。

リアルタイムの業務処理には、RDBが引き続き適しています。

構造化Tidyデータの目的は異なります。
長期保存、交換、検証、分析、AIによる歴史データの解釈のために、持ち運び可能で、自己完結性が高く、セマンティックモデルによって管理された表現を提供します。

RDB設計者から見ると、この表の形は一見不自然です。

しかし、それは正規化を捨てるためではありません。
セマンティックな分離を保ちながら、過去の業務記録全体を一緒に保存・移送できるようにするための設計です。


投稿日

カテゴリー:

投稿者:

タグ:

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です