ABDをまた考える
やっぱりこれはDB設計の技とだけ考えると痛い目に会うと思いますよ。
資料にあった売上のER図、あそこから請求金額を取得しようと思ったんですよ。ある請求期間内の売上金額を顧客単位で集計する訳です。
SQLはこうですかね。資料がない方はあいすみません。
SELECT 関連.顧客ID, SUM(明細.数量 * 商品.単価) FROM 売上_関連 関連 INNER JOIN 売上 ON 関連.売上ID = 売上.売上ID INNER JOIN 売上明細 明細 ON 関連.売上明細ID = 明細.売上明細ID INNER JOIN 商品 ON 関連.商品ID = 商品.商品ID WHERE 売上.日付 BETWEEN 請求期間FROM AND 請求期間TO GROUP BY 関連.顧客ID
あっなんか凄い簡単だ。
いや、そうじゃないんだ。あぶないあぶない。あやうくコロっと落とされる所だった。
例だと簡単過ぎちゃうので、消費税金額を売上テーブルに持つとしましょうよ。売上計上時に仮受消費税は認識されるの法則に乗っ取りまして。で、取引はBtoCなので総額表示には準じない、よって明細単位でなく売上テーブルに消費税金額を持つ。
よって今の所、売上テーブルには
- 売上ID
- 日付
- 消費税金額
の3つのカラムがあるとします。
さて、消費税金額も請求金額に含めないといけませんので、SQLはこうしないと上手い事取ってこれないんじゃないかな。
SELECT 請求.顧客ID, SUM(請求.請求金額) FROM ( SELECT 関連.顧客ID, 関連.売上ID, 売上.消費税金額 + SUM(明細.数量 * 商品.単価) AS 請求金額 FROM 売上_関連 関連 INNER JOIN 売上 ON 関連.売上ID = 売上.売上ID INNER JOIN 売上明細 明細 ON 関連.売上明細ID = 明細.売上明細ID INNER JOIN 商品 ON 関連.商品ID = 商品.商品ID WHERE 売上.日付 BETWEEN 請求期間FROM AND 請求期間TO GROUP BY 関連.顧客ID, 関連.売上ID, 売上.消費税金額 )請求 GROUP BY 請求.顧客ID
前のSQLみたくして取って来たら、消費税金額が明細の数だけ膨れちゃいますね。
えー、つまり、このSQLを書くためには、売上と売上明細の親子関連の構成について知っていなければならない訳です。
それが、ABD的な売上_関連テーブルからは読み取れないのです。
一般的なER図では、FKとリレーションシップのあり方から親子関係を見て取る事が出来ます。とは云え、ABDの前段階で主キーはすべからく機械的にIDにせよ、ってのがありますんでその時点で親子なんだかただの参照関連なんだか素直に見て取れなくなりますが、それでもFKにユニーク制約を付ける事でまあ判るかなあと。
じゃあABDの場合何処で親子関連構成である事を知るんだろう。
まあ売上と売上明細じゃ名前で明白なんですけど、そこは、どうかひとつ!バカのふりを御願いします。
ここで「データモデル = ビジネスモデリング?ちゃんちゃらおかしいぜ」と云う言葉が蘇ります。ABDはプロセスに注目してる訳で、データモデルから「えー業務上このデータとこのデータはこういう構成で〜」とかのビジネスモデリングを導き出すのはダメなのだと、あの煽りはABDへの大いなる伏線であったのかと、思った訳です。
主キーはIDとかm:mにしておけとかも全部伏線。
じゃあどこから見出し明細構成を読み取るのよ、と云うと、ここで今度は「DB設計はUIから!モデリング幻想は捨てること!」と云う言葉が蘇って来ましたよ。
そうか、画面と帳票から読み取るのが正しいって事か、と。だからちゃんとUIを気合入れて決める必要があって、しかも業務のあり方がすっと入ってくるようなUIにするべきかと。
なんだ、突っつこうと思ったら自己レスで終わってしまった。いやー難しいよなあ。
ここで1行目の、やっぱりこれはDB設計の技とだけ考えると痛い目に会うと思いますよ、に戻る。業務フロー即ちアクティビティをしっかりと定義して、それに沿ってUIをばっちり決めて、そこから始めないといかんのですね。そうじゃないとさっきみたく「さーて請求登録のSQLでも書こうかな〜」とか云う時に、消費税金額が本来の数十倍の請求金額を取得しちゃったりとか起きかねない。
うーむ。安易にまねっこしてはいけませんね。開発プロセス全体で考えないといけない。