連載 [第5回] :
即活用!ツールを活用したデータモデリング教科書的ではなく、現場にあったデータベース設計のコツ
2006年4月24日(月)
階層構造(パス方式)
再起型の検索方法を解決するために考えられたのが、「祖先をすべてパス情報として持つパス方式」です。図3はパス方式のエンティティです。図2の「親カテゴリ番号」の代わりに「カテゴリ番号パス」というアトリビュートを文字列型で用意しています。
表3はパス方式のデータ例です。この方式は該当項目の親だけでなく、階層トップから自分に至るまでのカテゴリ関連をパスの形で持っているのが特徴です。図3ではパスの連結記号に「~(チルダ)」を使っていますが、「\」を使ってもかまいません。
この方式のメリットは再帰検索にならないことです。例えば、表2のように「パソコン(カテゴリ番号011)関連の商品の売上合計を求める」という命題があった場合、表3のような条件で1回の指定で対象カテゴリデータを抽出できます。階層がどんなに深くても一発で検索できる便利な方式なので、階層構造のテーブル設計時に試してみてください。
検索条件
where カテゴリ番号パス like ‘%011~%’
where カテゴリ番号パス like ‘%011~%’
カテゴリ番号 | カテゴリ番号パス | カテゴリ名 |
---|---|---|
01 | 01~ | ハードウェア |
011 | 01~011~ | パソコン |
0111 | 01~011~0111~ | 本体 |
0112 | 01~011~0112~ | モニタ |
どこまで非正規化を行うかの判断
データベース設計で迷う点は、どこまで非正規化を行うかということではないでしょうか。一般に技術者は正論をいう傾向が強いので、「正規化は崩すべきじゃない」と主張する人が多いようです。しかし実際にシステムを構築する立場からすると、一概にそうともいい切れません。
図4は「Northwind」の「受注」「受注明細」と「顧客」「商品」エンティティです。このようなシンプルな構造においても、次のように非正規化を行うかどうかを考えるポイントは少なからずあります。以下、順番に考察してみましょう。
- 「受注明細」に金額を持つか
- 「受注」に合計金額を持つか
- 「受注」に顧客名、「受注明細」に商品名を持つか
「受注明細」エンティティに「金額」項目を持つか
図4は「受注明細」エンティティに「セット単価」という項目を持っています。「商品マスタ」にも「セット単価」という項目がありますが、「商品マスタ」の「単価」は変更される可能性があるので、「受注明細」エンティティに項目を持つのは当然といえます。また関係を明確にするために、「受注明細」エンティティの項目名を「受注時セット単価」とする人もいます。
「受注明細」エンティティの「セット単価」×「数量(これも受注数量という項目名にする人もいます)」が金額となりますが、この金額を受注明細の項目に用意しておくかどうかはちょっと迷います。この例のようなシンプルな構成なら、正規化したまま項目を持たないということでもよいでしょう。
しかし実際のシステムには消費税計算があって、受注時の消費税率やその丸め誤差の処理なども計算に加わります。その結果、消費税マスタの消費税率や丸め誤差の処理方法が後で変更された場合でも、受注明細の金額が変わってはいけません。
また金額がセットされていないと、BIツールなどで商品別受注金額などを集計する際に、いちいち計算で求める必要が生じます。それらを総合的に考慮した場合、明細列に金額を用意する方法が処理しやすいという判断も十分ありえるでしょう。
連載バックナンバー
Think ITメルマガ会員登録受付中
Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。